easytensor 1.0.1.0 → 2.0.0.0
raw patch · 73 files changed
+12413/−8879 lines, 73 filesdep +constraints-derivingdep +template-haskelldep ~basedep ~dimensionsPVP ok
version bump matches the API change (PVP)
Dependencies added: constraints-deriving, template-haskell
Dependency ranges changed: base, dimensions
API changes (from Hackage documentation)
- Numeric.DataFrame.Contraction: instance (Numeric.Type.List.ConcatList as bs asbs, Numeric.Dimensions.Dims.Dimensions as, Numeric.Dimensions.Dims.Dimensions bs, GHC.Num.Num t) => Numeric.DataFrame.Contraction.Contraction t as bs asbs
- Numeric.DataFrame.Family: data family DataFrame (t :: l) (xs :: [k])
- Numeric.DataFrame.Internal.Array.Class: broadcast :: PrimArray t a => t -> a
- Numeric.DataFrame.Internal.Array.Class: class PrimBytes t => PrimArray t a | a -> t
- Numeric.DataFrame.Internal.Array.Class: elemOffset :: PrimArray t a => a -> Int#
- Numeric.DataFrame.Internal.Array.Class: elemSize0 :: PrimArray t a => a -> Int#
- Numeric.DataFrame.Internal.Array.Class: fromElems :: PrimArray t a => Int# -> Int# -> ByteArray# -> a
- Numeric.DataFrame.Internal.Array.Class: gen# :: PrimArray t a => Int# -> (s -> (# s, t #)) -> s -> (# s, a #)
- Numeric.DataFrame.Internal.Array.Class: ix# :: PrimArray t a => Int# -> a -> t
- Numeric.DataFrame.Internal.Array.Class: ixOff :: PrimArray t a => Int -> a -> t
- Numeric.DataFrame.Internal.Array.Class: unsafeFromFlatList :: PrimArray t a => Int -> [t] -> a
- Numeric.DataFrame.Internal.Array.Class: upd# :: PrimArray t a => Int# -> Int# -> t -> a -> a
- Numeric.DataFrame.Internal.Array.Family: ArrayBase :: (# t | (# Int#, Int#, ByteArray#, Evidence (PrimBytes t) #) #) -> ArrayBase
- Numeric.DataFrame.Internal.Array.Family: ScalarBase :: t -> ScalarBase t
- Numeric.DataFrame.Internal.Array.Family: [ABase] :: (Array t ds ~ ArrayBase t ds, PrimBytes t) => ArraySing t ds
- Numeric.DataFrame.Internal.Array.Family: [AD2] :: Array t ds ~ DoubleX2 => ArraySing Double '[2]
- Numeric.DataFrame.Internal.Array.Family: [AD3] :: Array t ds ~ DoubleX3 => ArraySing Double '[3]
- Numeric.DataFrame.Internal.Array.Family: [AD4] :: Array t ds ~ DoubleX4 => ArraySing Double '[4]
- Numeric.DataFrame.Internal.Array.Family: [AF2] :: Array t ds ~ FloatX2 => ArraySing Float '[2]
- Numeric.DataFrame.Internal.Array.Family: [AF3] :: Array t ds ~ FloatX3 => ArraySing Float '[3]
- Numeric.DataFrame.Internal.Array.Family: [AF4] :: Array t ds ~ FloatX4 => ArraySing Float '[4]
- Numeric.DataFrame.Internal.Array.Family: [AScalar] :: Array t ds ~ ScalarBase t => ArraySing t '[]
- Numeric.DataFrame.Internal.Array.Family: [_unScalarBase] :: ScalarBase t -> t
- Numeric.DataFrame.Internal.Array.Family: aSing :: ArraySingleton t ds => ArraySing t ds
- Numeric.DataFrame.Internal.Array.Family: aSingEv :: ArraySing t ds -> Evidence (ArraySingleton t ds)
- Numeric.DataFrame.Internal.Array.Family: class ArraySingleton (t :: Type) (ds :: [Nat])
- Numeric.DataFrame.Internal.Array.Family: data ArrayBase (t :: Type) (ds :: [Nat])
- Numeric.DataFrame.Internal.Array.Family: data ArraySing t (ds :: [Nat])
- Numeric.DataFrame.Internal.Array.Family: inferASing :: forall t ds. (PrimBytes t, Dimensions ds) => Evidence (ArraySingleton t ds)
- Numeric.DataFrame.Internal.Array.Family: inferEq :: forall t ds. (Eq t, ArraySingleton t ds) => Evidence (Eq (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: inferFloating :: forall t ds. (Floating t, ArraySingleton t ds) => Evidence (Floating (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: inferFractional :: forall t ds. (Fractional t, ArraySingleton t ds) => Evidence (Fractional (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: inferNum :: forall t ds. (Num t, ArraySingleton t ds) => Evidence (Num (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: inferOrd :: forall t ds. (Ord t, ArraySingleton t ds) => Evidence (Ord (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: inferPrim :: forall t ds. (PrimBytes t, ArraySingleton t ds, Dimensions ds) => Evidence (PrimBytes (Array t ds), PrimArray t (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: inferPrimElem :: forall t d ds. ArraySingleton t (d : ds) => Evidence (PrimBytes t)
- Numeric.DataFrame.Internal.Array.Family: inferShow :: forall t ds. (Show t, Dimensions ds, ArraySingleton t ds) => Evidence (Show (Array t ds))
- Numeric.DataFrame.Internal.Array.Family: instance (Numeric.DataFrame.Internal.Array.Family.Array t ds Data.Type.Equality.~ Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds, Numeric.PrimBytes.PrimBytes t) => Numeric.DataFrame.Internal.Array.Family.ArraySingleton t ds
- Numeric.DataFrame.Internal.Array.Family: instance GHC.Classes.Eq (Numeric.DataFrame.Internal.Array.Family.ArraySing t ds)
- Numeric.DataFrame.Internal.Array.Family: instance GHC.Classes.Ord (Numeric.DataFrame.Internal.Array.Family.ArraySing t ds)
- Numeric.DataFrame.Internal.Array.Family: instance GHC.Show.Show (Numeric.DataFrame.Internal.Array.Family.ArraySing t ds)
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton GHC.Types.Double '[2]
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton GHC.Types.Double '[3]
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton GHC.Types.Double '[4]
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton GHC.Types.Float '[2]
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton GHC.Types.Float '[3]
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton GHC.Types.Float '[4]
- Numeric.DataFrame.Internal.Array.Family: instance Numeric.DataFrame.Internal.Array.Family.ArraySingleton t '[]
- Numeric.DataFrame.Internal.Array.Family: newtype ScalarBase t
- Numeric.DataFrame.Internal.Array.Family: type family Array (t :: Type) (ds :: [Nat]) = (v :: Type) | v -> t ds
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: ArrayBase :: (# t | (# Int#, Int#, ByteArray#, Evidence (PrimBytes t) #) #) -> ArrayBase
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: data ArrayBase (t :: Type) (ds :: [Nat])
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance (Numeric.Dimensions.Dims.Dimensions ds, GHC.Show.Show t) => GHC.Show.Show (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance (Numeric.PrimBytes.PrimBytes t, Numeric.Dimensions.Dims.Dimensions ds) => Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Classes.Eq t => GHC.Classes.Eq (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Classes.Ord t => GHC.Classes.Ord (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase GHC.Types.Double ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase GHC.Types.Float ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Enum.Bounded t => GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Float.Floating t => GHC.Float.Floating (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Num.Num t => GHC.Num.Num (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance GHC.Real.Fractional t => GHC.Real.Fractional (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.ArrayBase: instance Numeric.PrimBytes.PrimBytes t => Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.DataFrame.Internal.Array.Family.ArrayBase.ArrayBase t ds)
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: DoubleX2# :: Double# -> Double# -> DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: data DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Classes.Eq Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Classes.Ord Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Enum.Bounded Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Float.Floating Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Num.Num Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Real.Fractional Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance GHC.Show.Show Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance Numeric.DataFrame.Internal.Array.Class.PrimArray GHC.Types.Double Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX2: instance Numeric.PrimBytes.PrimBytes Numeric.DataFrame.Internal.Array.Family.DoubleX2.DoubleX2
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: DoubleX3# :: Double# -> Double# -> Double# -> DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: data DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Classes.Eq Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Classes.Ord Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Enum.Bounded Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Float.Floating Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Num.Num Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Real.Fractional Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance GHC.Show.Show Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance Numeric.DataFrame.Internal.Array.Class.PrimArray GHC.Types.Double Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX3: instance Numeric.PrimBytes.PrimBytes Numeric.DataFrame.Internal.Array.Family.DoubleX3.DoubleX3
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: DoubleX4# :: Double# -> Double# -> Double# -> Double# -> DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: data DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Classes.Eq Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Classes.Ord Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Enum.Bounded Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Float.Floating Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Num.Num Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Real.Fractional Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance GHC.Show.Show Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance Numeric.DataFrame.Internal.Array.Class.PrimArray GHC.Types.Double Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.DoubleX4: instance Numeric.PrimBytes.PrimBytes Numeric.DataFrame.Internal.Array.Family.DoubleX4.DoubleX4
- Numeric.DataFrame.Internal.Array.Family.FloatX2: FloatX2# :: Float# -> Float# -> FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: data FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Classes.Eq Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Classes.Ord Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Enum.Bounded Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Float.Floating Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Num.Num Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Real.Fractional Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance GHC.Show.Show Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance Numeric.DataFrame.Internal.Array.Class.PrimArray GHC.Types.Float Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX2: instance Numeric.PrimBytes.PrimBytes Numeric.DataFrame.Internal.Array.Family.FloatX2.FloatX2
- Numeric.DataFrame.Internal.Array.Family.FloatX3: FloatX3# :: Float# -> Float# -> Float# -> FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: data FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Classes.Eq Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Classes.Ord Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Enum.Bounded Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Float.Floating Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Num.Num Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Real.Fractional Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance GHC.Show.Show Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance Numeric.DataFrame.Internal.Array.Class.PrimArray GHC.Types.Float Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX3: instance Numeric.PrimBytes.PrimBytes Numeric.DataFrame.Internal.Array.Family.FloatX3.FloatX3
- Numeric.DataFrame.Internal.Array.Family.FloatX4: FloatX4# :: Float# -> Float# -> Float# -> Float# -> FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: data FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Classes.Eq Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Classes.Ord Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Enum.Bounded Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Float.Floating Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Num.Num Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Real.Fractional Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance GHC.Show.Show Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance Numeric.DataFrame.Internal.Array.Class.PrimArray GHC.Types.Float Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.FloatX4: instance Numeric.PrimBytes.PrimBytes Numeric.DataFrame.Internal.Array.Family.FloatX4.FloatX4
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: ScalarBase :: t -> ScalarBase t
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: [_unScalarBase] :: ScalarBase t -> t
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Classes.Eq t => GHC.Classes.Eq (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Classes.Ord t => GHC.Classes.Ord (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase GHC.Types.Double)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase GHC.Types.Float)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Enum.Bounded t => GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Enum.Enum t => GHC.Enum.Enum (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Float.Floating t => GHC.Float.Floating (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Float.RealFloat t => GHC.Float.RealFloat (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Num.Num t => GHC.Num.Num (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Read.Read t => GHC.Read.Read (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Real.Fractional t => GHC.Real.Fractional (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Real.Integral t => GHC.Real.Integral (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Real.Real t => GHC.Real.Real (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Real.RealFrac t => GHC.Real.RealFrac (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance GHC.Show.Show t => GHC.Show.Show (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance Numeric.PrimBytes.PrimBytes t => Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: instance Numeric.PrimBytes.PrimBytes t => Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Internal.Array.Family.ScalarBase.ScalarBase t)
- Numeric.DataFrame.Internal.Array.Family.ScalarBase: newtype ScalarBase t
- Numeric.DataFrame.Internal.Array.PrimOps: inftyD :: Double
- Numeric.DataFrame.Internal.Array.PrimOps: inftyF :: Float
- Numeric.DataFrame.Internal.Array.PrimOps: loop# :: Int# -> Int# -> Int# -> (Int# -> State# s -> State# s) -> State# s -> State# s
- Numeric.DataFrame.Internal.Array.PrimOps: loop1# :: Int# -> (Int# -> State# s -> State# s) -> State# s -> State# s
- Numeric.DataFrame.Internal.Array.PrimOps: loop1a# :: Int# -> (Int# -> a -> a) -> a -> a
- Numeric.DataFrame.Internal.Array.PrimOps: loopWithI# :: Int# -> Int# -> Int# -> (Int# -> Int# -> State# s -> State# s) -> State# s -> State# s
- Numeric.DataFrame.Internal.Array.PrimOps: minInt# :: Int# -> Int# -> Int#
- Numeric.DataFrame.Internal.Array.PrimOps: overDim_# :: Dims (ds :: [k]) -> (Idxs ds -> Int# -> State# s -> State# s) -> Int# -> Int# -> State# s -> State# s
- Numeric.DataFrame.Internal.Array.PrimOps: overDim_'# :: Dims (ds :: [k]) -> (Idxs ds -> Int# -> State# s -> (# State# s, Int# #)) -> Int# -> State# s -> (# State# s, Int# #)
- Numeric.DataFrame.Shape: (<+:>) :: forall (ds :: [Nat]) (n :: Nat) (m :: Nat) (t :: Type). (PrimBytes (DataFrame t (ds +: n)), PrimBytes (DataFrame t ds), PrimBytes (DataFrame t (ds +: m)), m ~ (n + 1)) => DataFrame t (ds +: n) -> DataFrame t ds -> DataFrame t (ds +: m)
- Numeric.DataFrame.Shape: (<::>) :: forall (ds :: [Nat]) (t :: Type). (PrimBytes (DataFrame t ds), PrimBytes (DataFrame t ds), PrimBytes (DataFrame t (ds +: 2 :: [Nat]))) => DataFrame t ds -> DataFrame t ds -> DataFrame t (ds +: 2 :: [Nat])
- Numeric.DataFrame.Shape: (<:>) :: forall (n :: Nat) (m :: Nat) (npm :: Nat) (ds :: [Nat]) (t :: Type). (PrimBytes (DataFrame t (ds +: n)), PrimBytes (DataFrame t (ds +: m)), PrimBytes (DataFrame t (ds +: npm)), npm ~ (n + m), n ~ (npm - m), m ~ (npm - n)) => DataFrame t (ds +: n) -> DataFrame t (ds +: m) -> DataFrame t (ds +: npm)
- Numeric.DataFrame.Shape: class DataFrameToList (t :: Type) (ds :: [k]) (z :: k)
- Numeric.DataFrame.Shape: fromList :: forall m ns t. (Dimensions ns, PrimBytes t) => Dim m -> [DataFrame t ns] -> Maybe (DataFrame t (AsXDims ns +: XN m))
- Numeric.DataFrame.Shape: fromListN :: forall (m :: Nat) (ns :: [Nat]) (t :: Type). (Dimensions ns, PrimBytes t) => Dim m -> Int -> [DataFrame t ns] -> Maybe (DataFrame t (AsXDims ns +: XN m))
- Numeric.DataFrame.Shape: fromScalar :: SubSpace t '[] ds ds => Scalar t -> DataFrame t ds
- Numeric.DataFrame.Shape: infixl 5 <+:>
- Numeric.DataFrame.Shape: instance (Numeric.Dimensions.Dims.Dimensions (ns Numeric.Type.List.+: z), Numeric.PrimBytes.PrimBytes t) => Numeric.DataFrame.Shape.DataFrameToList t ns z
- Numeric.DataFrame.Shape: instance Numeric.DataFrame.Shape.DataFrameToList t xns xz
- Numeric.DataFrame.Shape: toList :: DataFrameToList t ds z => DataFrame t (ds +: z) -> [DataFrame t ds]
- Numeric.DataFrame.SubSpace: (!.) :: forall t as bs asbs. SubSpace t as bs asbs => Idxs bs -> DataFrame t asbs -> DataFrame t as
- Numeric.DataFrame.SubSpace: infixr 4 !.
- Numeric.DataFrame.SubSpace: instance (Numeric.Type.List.ConcatList as bs asbs, Numeric.Dimensions.Dims.Dimensions as, Numeric.Dimensions.Dims.Dimensions bs, Numeric.Dimensions.Dims.Dimensions asbs, Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.DataFrame.Family.DataFrame t as), Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.DataFrame.Family.DataFrame t asbs), Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Family.DataFrame t as), Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Family.DataFrame t asbs)) => Numeric.DataFrame.SubSpace.SubSpace t as bs asbs
- Numeric.DataFrame.Type: Idx :: Word -> Idx
- Numeric.DataFrame.Type: [unIdx] :: Idx -> Word
- Numeric.DataFrame.Type: class DataFrameInference (t :: l)
- Numeric.DataFrame.Type: class Dim1 (t :: [k] -> Type) (ds :: [k])
- Numeric.DataFrame.Type: class Dim2 (t :: [k] -> Type) (ds :: [k])
- Numeric.DataFrame.Type: class Dim3 (t :: [k] -> Type) (ds :: [k])
- Numeric.DataFrame.Type: dim1 :: Dim1 t ds => t ds -> Dim (Head ds)
- Numeric.DataFrame.Type: dim2 :: Dim2 t ds => t ds -> Dim (Head (Tail ds))
- Numeric.DataFrame.Type: dim3 :: Dim3 t ds => t ds -> Dim (Head (Tail (Tail ds)))
- Numeric.DataFrame.Type: dimSize1 :: Dim1 t ds => t ds -> Word
- Numeric.DataFrame.Type: dimSize2 :: Dim2 t ds => t ds -> Word
- Numeric.DataFrame.Type: dimSize3 :: Dim3 t ds => t ds -> Word
- Numeric.DataFrame.Type: inferASing :: (DataFrameInference t, AllTypes PrimBytes t, Dimensions ds) => DataFrame t ds -> Evidence (ArraySingletons t ds)
- Numeric.DataFrame.Type: inferASing' :: forall t ds. (DataFrameInference t, AllTypes PrimBytes t, Dimensions ds) => Evidence (ArraySingletons t ds)
- Numeric.DataFrame.Type: inferEq :: (DataFrameInference t, AllTypes Eq t, ArraySingletons t ds) => DataFrame t ds -> Evidence (Eq (DataFrame t ds))
- Numeric.DataFrame.Type: inferEq' :: forall t ds. (DataFrameInference t, AllTypes Eq t, ArraySingletons t ds) => Evidence (Eq (DataFrame t ds))
- Numeric.DataFrame.Type: inferFloating :: forall t ds. (Floating t, ArraySingleton t ds) => DataFrame t ds -> Evidence (Floating (DataFrame t ds))
- Numeric.DataFrame.Type: inferFloating' :: forall t ds. (Floating t, ArraySingleton t ds) => Evidence (Floating (DataFrame t ds))
- Numeric.DataFrame.Type: inferFractional :: forall t ds. (Fractional t, ArraySingleton t ds) => DataFrame t ds -> Evidence (Fractional (DataFrame t ds))
- Numeric.DataFrame.Type: inferFractional' :: forall t ds. (Fractional t, ArraySingleton t ds) => Evidence (Fractional (DataFrame t ds))
- Numeric.DataFrame.Type: inferNum :: forall t ds. (Num t, ArraySingletons t ds) => DataFrame t ds -> Evidence (Num (DataFrame t ds))
- Numeric.DataFrame.Type: inferNum' :: forall t ds. (Num t, ArraySingletons t ds) => Evidence (Num (DataFrame t ds))
- Numeric.DataFrame.Type: inferOrd :: forall t ds. (Ord t, ArraySingleton t ds) => DataFrame t ds -> Evidence (Ord (DataFrame t ds))
- Numeric.DataFrame.Type: inferOrd' :: forall t ds. (Ord t, ArraySingleton t ds) => Evidence (Ord (DataFrame t ds))
- Numeric.DataFrame.Type: inferPrim :: (DataFrameInference t, AllTypes PrimBytes t, ArraySingletons t ds, Dimensions ds) => DataFrame t ds -> Evidence (PrimFrames t ds)
- Numeric.DataFrame.Type: inferPrim' :: forall t ds. (DataFrameInference t, AllTypes PrimBytes t, ArraySingletons t ds, Dimensions ds) => Evidence (PrimFrames t ds)
- Numeric.DataFrame.Type: inferPrimElem' :: forall t ds. (DataFrameInference t, ArraySingletons t ds, ds ~ (Head ds : Tail ds)) => Evidence (AllTypes PrimBytes t)
- Numeric.DataFrame.Type: inferShow :: (DataFrameInference t, AllTypes Show t, ArraySingletons t ds, Dimensions ds) => DataFrame t ds -> Evidence (Show (DataFrame t ds))
- Numeric.DataFrame.Type: inferShow' :: forall t ds. (DataFrameInference t, AllTypes Show t, ArraySingletons t ds, Dimensions ds) => Evidence (Show (DataFrame t ds))
- Numeric.DataFrame.Type: instance (GHC.Read.Read (Numeric.DataFrame.Internal.Array.Family.Array t ds), Numeric.Dimensions.Dims.Dimensions ds) => GHC.Read.Read (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance (GHC.Show.Show (Numeric.DataFrame.Internal.Array.Family.Array t ds), Numeric.Dimensions.Dims.Dimensions ds) => GHC.Show.Show (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance (Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.DataFrame.Internal.Array.Family.Array t ds), Numeric.PrimBytes.PrimBytes t) => Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance (Numeric.Dimensions.Dims.Dimensions ds, Numeric.DataFrame.Type.ImplAllows GHC.Show.Show ts ds) => GHC.Show.Show (Numeric.DataFrame.Family.DataFrame ts ds)
- Numeric.DataFrame.Type: instance GHC.Classes.Eq (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Classes.Eq (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Classes.Ord (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Classes.Ord (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Enum.Bounded (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Enum.Bounded (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Enum.Enum (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Enum.Enum (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Float.Floating (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Float.Floating (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Float.RealFloat (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Float.RealFloat (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Num.Num (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Num.Num (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Real.Fractional (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Real.Fractional (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Real.Integral (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Real.Integral (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Real.Real (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Real.Real (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance GHC.Real.RealFrac (Numeric.DataFrame.Internal.Array.Family.Array t ds) => GHC.Real.RealFrac (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance Numeric.DataFrame.Type.DataFrameInference t
- Numeric.DataFrame.Type: instance Numeric.DataFrame.Type.ImplAllows GHC.Classes.Eq ts ds => GHC.Classes.Eq (Numeric.DataFrame.Family.DataFrame ts ds)
- Numeric.DataFrame.Type: instance Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Internal.Array.Family.Array t ds) => Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance Numeric.TypedList.RepresentableList ts => Numeric.DataFrame.Type.DataFrameInference ts
- Numeric.DataFrame.Type: instance forall k (d :: k) (ds :: [k]) (t :: [k] -> Type). Numeric.Dimensions.Dims.Dimensions (d : ds) => Numeric.DataFrame.Type.Dim1 t (d : ds)
- Numeric.DataFrame.Type: instance forall k (d :: k) (ds :: [k]). Numeric.DataFrame.Type.Dim1 (Numeric.TypedList.TypedList Numeric.Dim.Dim) (d : ds)
- Numeric.DataFrame.Type: instance forall k (d1 :: k) (d2 :: k) (d3 :: k) (ds :: [k]) (t :: [k] -> Type). Numeric.Dimensions.Dims.Dimensions (d1 : d2 : d3 : ds) => Numeric.DataFrame.Type.Dim3 t (d1 : d2 : d3 : ds)
- Numeric.DataFrame.Type: instance forall k (d1 :: k) (d2 :: k) (d3 :: k) (ds :: [k]). Numeric.DataFrame.Type.Dim3 (Numeric.TypedList.TypedList Numeric.Dim.Dim) (d1 : d2 : d3 : ds)
- Numeric.DataFrame.Type: instance forall k (d1 :: k) (d2 :: k) (ds :: [k]) (t :: [k] -> Type). Numeric.Dimensions.Dims.Dimensions (d1 : d2 : ds) => Numeric.DataFrame.Type.Dim2 t (d1 : d2 : ds)
- Numeric.DataFrame.Type: instance forall k (d1 :: k) (d2 :: k) (ds :: [k]). Numeric.DataFrame.Type.Dim2 (Numeric.TypedList.TypedList Numeric.Dim.Dim) (d1 : d2 : ds)
- Numeric.DataFrame.Type: instance forall k l (t :: l) (ds :: [k]). Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Family.DataFrame t ds) => Foreign.Storable.Storable (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance forall l (t :: l) (ds :: [Numeric.Dim.XNat]). (Numeric.DataFrame.Type.AllTypes GHC.Classes.Eq t, Numeric.DataFrame.Type.DataFrameInference t) => GHC.Classes.Eq (Numeric.DataFrame.Family.DataFrame t ds)
- Numeric.DataFrame.Type: instance forall l (t :: l) (xns :: [Numeric.Dim.XNat]). (Numeric.DataFrame.Type.AllTypes GHC.Show.Show t, Numeric.DataFrame.Type.DataFrameInference t) => GHC.Show.Show (Numeric.DataFrame.Family.DataFrame t xns)
- Numeric.DataFrame.Type: instance forall l (t :: l). (Numeric.DataFrame.Type.AllTypes GHC.Classes.Eq t, Numeric.DataFrame.Type.DataFrameInference t) => GHC.Classes.Eq (Numeric.DataFrame.Type.SomeDataFrame t)
- Numeric.DataFrame.Type: instance forall l (t :: l). (Numeric.DataFrame.Type.AllTypes GHC.Show.Show t, Numeric.DataFrame.Type.DataFrameInference t) => GHC.Show.Show (Numeric.DataFrame.Type.SomeDataFrame t)
- Numeric.DataFrame.Type: instance forall l1 (l2 :: l1) (d :: Numeric.Dim.XNat) (ds :: [Numeric.Dim.XNat]). Numeric.DataFrame.Type.Dim1 (Numeric.DataFrame.Family.DataFrame l2) (d : ds)
- Numeric.DataFrame.Type: instance forall l1 (l2 :: l1) (d1 :: Numeric.Dim.XNat) (d2 :: Numeric.Dim.XNat) (d3 :: Numeric.Dim.XNat) (ds :: [Numeric.Dim.XNat]). Numeric.DataFrame.Type.Dim3 (Numeric.DataFrame.Family.DataFrame l2) (d1 : d2 : d3 : ds)
- Numeric.DataFrame.Type: instance forall l1 (l2 :: l1) (d1 :: Numeric.Dim.XNat) (d2 :: Numeric.Dim.XNat) (ds :: [Numeric.Dim.XNat]). Numeric.DataFrame.Type.Dim2 (Numeric.DataFrame.Family.DataFrame l2) (d1 : d2 : ds)
- Numeric.DataFrame.Type: newtype Idx (n :: k) :: forall k. () => k -> Type
- Numeric.DataFrame.Type: unsafeFromFlatList :: PrimArray t a => Int -> [t] -> a
- Numeric.Matrix: instance (Numeric.Dim.KnownDim n, GHC.Classes.Ord t, GHC.Real.Fractional t, Numeric.PrimBytes.PrimBytes t, Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Matrix.Class.Matrix t n n)) => Numeric.Matrix.Class.MatrixDeterminant t n
- Numeric.Matrix: instance (Numeric.Dim.KnownDim n, GHC.Classes.Ord t, GHC.Real.Fractional t, Numeric.PrimBytes.PrimBytes t, Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Matrix.Class.Matrix t n n)) => Numeric.Matrix.Class.MatrixLU t n
- Numeric.Matrix: instance (Numeric.Dim.KnownDim n, GHC.Classes.Ord t, GHC.Real.Fractional t, Numeric.PrimBytes.PrimBytes t, Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Matrix.Class.Matrix t n n), Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Vector.Vector t n), Numeric.PrimBytes.PrimBytes (Numeric.Vector.Vector t n), Numeric.PrimBytes.PrimBytes (Numeric.Matrix.Class.Matrix t n n)) => Numeric.Matrix.Class.MatrixInverse t n
- Numeric.Matrix: instance (Numeric.Dim.KnownDim n, Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Matrix.Class.Matrix t n n), GHC.Num.Num t) => Numeric.Matrix.Class.SquareMatrix t n
- Numeric.Matrix: instance (Numeric.Dim.KnownDim n, Numeric.Dim.KnownDim m, Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Matrix.Class.Matrix t n m), Numeric.DataFrame.Internal.Array.Class.PrimArray t (Numeric.Matrix.Class.Matrix t m n)) => Numeric.Matrix.Class.MatrixTranspose t n m
- Numeric.Matrix: instance Numeric.Matrix.Class.MatrixTranspose t xn xm
- Numeric.Matrix.Class: LUFact :: Matrix t n n -> Matrix t n n -> Matrix t n n -> Scalar t -> LUFact t n
- Numeric.Matrix.Class: [luLower] :: LUFact t n -> Matrix t n n
- Numeric.Matrix.Class: [luPermSign] :: LUFact t n -> Scalar t
- Numeric.Matrix.Class: [luPerm] :: LUFact t n -> Matrix t n n
- Numeric.Matrix.Class: [luUpper] :: LUFact t n -> Matrix t n n
- Numeric.Matrix.Class: class HomTransform4 t
- Numeric.Matrix.Class: class MatrixDeterminant t (n :: Nat)
- Numeric.Matrix.Class: class MatrixInverse t (n :: Nat)
- Numeric.Matrix.Class: class MatrixLU t (n :: Nat)
- Numeric.Matrix.Class: class MatrixTranspose t (n :: k) (m :: k)
- Numeric.Matrix.Class: class SquareMatrix t (n :: Nat)
- Numeric.Matrix.Class: data LUFact t n
- Numeric.Matrix.Class: det :: MatrixDeterminant t n => Matrix t n n -> Scalar t
- Numeric.Matrix.Class: diag :: SquareMatrix t n => Scalar t -> Matrix t n n
- Numeric.Matrix.Class: eye :: SquareMatrix t n => Matrix t n n
- Numeric.Matrix.Class: fromHom :: HomTransform4 t => Vector t 4 -> Vector t 3
- Numeric.Matrix.Class: instance forall k t (n :: k). (GHC.Classes.Eq (Numeric.Matrix.Class.Matrix t n n), GHC.Classes.Eq t) => GHC.Classes.Eq (Numeric.Matrix.Class.LUFact t n)
- Numeric.Matrix.Class: instance forall k t (n :: k). (GHC.Show.Show (Numeric.Matrix.Class.Matrix t n n), GHC.Show.Show t) => GHC.Show.Show (Numeric.Matrix.Class.LUFact t n)
- Numeric.Matrix.Class: inverse :: MatrixInverse t n => Matrix t n n -> Matrix t n n
- Numeric.Matrix.Class: lookAt :: HomTransform4 t => Vector t 3 -> Vector t 3 -> Vector t 3 -> Matrix t 4 4
- Numeric.Matrix.Class: lu :: MatrixLU t n => Matrix t n n -> LUFact t n
- Numeric.Matrix.Class: orthogonal :: HomTransform4 t => t -> t -> t -> t -> Matrix t 4 4
- Numeric.Matrix.Class: perspective :: HomTransform4 t => t -> t -> t -> t -> Matrix t 4 4
- Numeric.Matrix.Class: rotate :: HomTransform4 t => Vector t 3 -> t -> Matrix t 4 4
- Numeric.Matrix.Class: rotateEuler :: HomTransform4 t => t -> t -> t -> Matrix t 4 4
- Numeric.Matrix.Class: rotateX :: HomTransform4 t => t -> Matrix t 4 4
- Numeric.Matrix.Class: rotateY :: HomTransform4 t => t -> Matrix t 4 4
- Numeric.Matrix.Class: rotateZ :: HomTransform4 t => t -> Matrix t 4 4
- Numeric.Matrix.Class: toHomPoint :: HomTransform4 t => Vector t 3 -> Vector t 4
- Numeric.Matrix.Class: toHomVector :: HomTransform4 t => Vector t 3 -> Vector t 4
- Numeric.Matrix.Class: trace :: SquareMatrix t n => Matrix t n n -> Scalar t
- Numeric.Matrix.Class: translate3 :: HomTransform4 t => Vector t 3 -> Matrix t 4 4
- Numeric.Matrix.Class: translate4 :: HomTransform4 t => Vector t 4 -> Matrix t 4 4
- Numeric.Matrix.Class: transpose :: MatrixTranspose t n m => Matrix t n m -> Matrix t m n
- Numeric.Matrix.Class: type Mat22d = Matrix Double 2 2
- Numeric.Matrix.Class: type Mat22f = Matrix Float 2 2
- Numeric.Matrix.Class: type Mat23d = Matrix Double 2 3
- Numeric.Matrix.Class: type Mat23f = Matrix Float 2 3
- Numeric.Matrix.Class: type Mat24d = Matrix Double 2 4
- Numeric.Matrix.Class: type Mat24f = Matrix Float 2 4
- Numeric.Matrix.Class: type Mat32d = Matrix Double 3 2
- Numeric.Matrix.Class: type Mat32f = Matrix Float 3 2
- Numeric.Matrix.Class: type Mat33d = Matrix Double 3 3
- Numeric.Matrix.Class: type Mat33f = Matrix Float 3 3
- Numeric.Matrix.Class: type Mat34d = Matrix Double 3 4
- Numeric.Matrix.Class: type Mat34f = Matrix Float 3 4
- Numeric.Matrix.Class: type Mat42d = Matrix Double 4 2
- Numeric.Matrix.Class: type Mat42f = Matrix Float 4 2
- Numeric.Matrix.Class: type Mat43d = Matrix Double 4 3
- Numeric.Matrix.Class: type Mat43f = Matrix Float 4 3
- Numeric.Matrix.Class: type Mat44d = Matrix Double 4 4
- Numeric.Matrix.Class: type Mat44f = Matrix Float 4 4
- Numeric.Matrix.Class: type Matrix (t :: l) (n :: k) (m :: k) = DataFrame t '[n, m]
- Numeric.PrimBytes: instance (Numeric.PrimBytes.GPrimBytes f, Numeric.PrimBytes.GPrimBytes g) => Numeric.PrimBytes.GPrimBytes (f GHC.Generics.:*: g)
- Numeric.PrimBytes: instance (Numeric.PrimBytes.GPrimBytes f, Numeric.PrimBytes.GPrimBytes g) => Numeric.PrimBytes.GPrimBytes (f GHC.Generics.:+: g)
- Numeric.PrimBytes: instance (Numeric.TypedList.RepresentableList xs, Numeric.Type.List.All Numeric.PrimBytes.PrimBytes xs) => Numeric.PrimBytes.PrimBytes (Numeric.Tuple.Lazy.Tuple xs)
- Numeric.PrimBytes: instance (Numeric.TypedList.RepresentableList xs, Numeric.Type.List.All Numeric.PrimBytes.PrimBytes xs) => Numeric.PrimBytes.PrimBytes (Numeric.Tuple.Strict.Tuple xs)
- Numeric.PrimBytes: instance Numeric.PrimBytes.GPrimBytes f => Numeric.PrimBytes.GPrimBytes (GHC.Generics.M1 i c f)
- Numeric.PrimBytes: instance Numeric.PrimBytes.PrimBytes (Numeric.Dimensions.Idxs.Idx x)
- Numeric.PrimBytes: instance Numeric.PrimBytes.PrimBytes a => Numeric.PrimBytes.PrimBytes [a]
- Numeric.PrimBytes: instance Numeric.TypedList.RepresentableList xs => Numeric.PrimBytes.PrimBytes (Numeric.Dimensions.Idxs.Idxs xs)
- Numeric.Quaternion: -- a 3D vector
- Numeric.Quaternion: -- where <tt>w</tt> is an argument, and <tt>x y z</tt> are components of
- Numeric.Quaternion: unpackQ :: Quaternion t => Quater t -> (t, t, t, t)
- Numeric.Semigroup: (<>) :: Semigroup a => a -> a -> a
- Numeric.Semigroup: All :: Bool -> All
- Numeric.Semigroup: Any :: Bool -> Any
- Numeric.Semigroup: Arg :: a -> b -> Arg a b
- Numeric.Semigroup: Dual :: a -> Dual a
- Numeric.Semigroup: Endo :: (a -> a) -> Endo a
- Numeric.Semigroup: First :: a -> First a
- Numeric.Semigroup: Last :: a -> Last a
- Numeric.Semigroup: Max :: a -> Max a
- Numeric.Semigroup: Min :: a -> Min a
- Numeric.Semigroup: MinMax :: a -> a -> MinMax a
- Numeric.Semigroup: Option :: Maybe a -> Option a
- Numeric.Semigroup: Product :: a -> Product a
- Numeric.Semigroup: Sum :: a -> Sum a
- Numeric.Semigroup: WrapMonoid :: m -> WrappedMonoid m
- Numeric.Semigroup: [appEndo] :: Endo a -> a -> a
- Numeric.Semigroup: [getAll] :: All -> Bool
- Numeric.Semigroup: [getAny] :: Any -> Bool
- Numeric.Semigroup: [getDual] :: Dual a -> a
- Numeric.Semigroup: [getFirst] :: First a -> a
- Numeric.Semigroup: [getLast] :: Last a -> a
- Numeric.Semigroup: [getMax] :: Max a -> a
- Numeric.Semigroup: [getMin] :: Min a -> a
- Numeric.Semigroup: [getOption] :: Option a -> Maybe a
- Numeric.Semigroup: [getProduct] :: Product a -> a
- Numeric.Semigroup: [getSum] :: Sum a -> a
- Numeric.Semigroup: [unwrapMonoid] :: WrappedMonoid m -> m
- Numeric.Semigroup: class Semigroup a => Monoid a
- Numeric.Semigroup: class Semigroup a
- Numeric.Semigroup: cycle1 :: Semigroup m => m -> m
- Numeric.Semigroup: data Arg a b
- Numeric.Semigroup: data MinMax a
- Numeric.Semigroup: diff :: Semigroup m => m -> Endo m
- Numeric.Semigroup: foldMap' :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
- Numeric.Semigroup: fromOption :: a -> Option a -> a
- Numeric.Semigroup: infixr 6 <>
- Numeric.Semigroup: instance (GHC.Classes.Ord a, GHC.Enum.Bounded a) => GHC.Base.Monoid (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance (GHC.Num.Num a, GHC.Classes.Ord a) => GHC.Num.Num (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance Control.Monad.Fix.MonadFix Numeric.Semigroup.MinMax
- Numeric.Semigroup: instance Control.Monad.Fix.MonadFix Numeric.Semigroup.Option
- Numeric.Semigroup: instance Data.Data.Data a => Data.Data.Data (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance Data.Data.Data a => Data.Data.Data (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance Data.Foldable.Foldable Numeric.Semigroup.Option
- Numeric.Semigroup: instance Data.Traversable.Traversable Numeric.Semigroup.Option
- Numeric.Semigroup: instance GHC.Base.Alternative Numeric.Semigroup.Option
- Numeric.Semigroup: instance GHC.Base.Applicative Numeric.Semigroup.MinMax
- Numeric.Semigroup: instance GHC.Base.Applicative Numeric.Semigroup.Option
- Numeric.Semigroup: instance GHC.Base.Functor Numeric.Semigroup.MinMax
- Numeric.Semigroup: instance GHC.Base.Functor Numeric.Semigroup.Option
- Numeric.Semigroup: instance GHC.Base.Monad Numeric.Semigroup.MinMax
- Numeric.Semigroup: instance GHC.Base.Monad Numeric.Semigroup.Option
- Numeric.Semigroup: instance GHC.Base.Semigroup a => GHC.Base.Monoid (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance GHC.Classes.Eq a => GHC.Classes.Eq (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Classes.Eq a => GHC.Classes.Eq (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance GHC.Classes.Ord a => GHC.Base.Semigroup (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Classes.Ord a => GHC.Classes.Ord (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Classes.Ord a => GHC.Classes.Ord (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Generics.Generic (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Generics.Generic (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance GHC.Generics.Generic1 Numeric.Semigroup.MinMax
- Numeric.Semigroup: instance GHC.Generics.Generic1 Numeric.Semigroup.Option
- Numeric.Semigroup: instance GHC.Read.Read a => GHC.Read.Read (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Read.Read a => GHC.Read.Read (Numeric.Semigroup.Option a)
- Numeric.Semigroup: instance GHC.Show.Show a => GHC.Show.Show (Numeric.Semigroup.MinMax a)
- Numeric.Semigroup: instance GHC.Show.Show a => GHC.Show.Show (Numeric.Semigroup.Option a)
- Numeric.Semigroup: mappend :: Monoid a => a -> a -> a
- Numeric.Semigroup: mconcat :: Monoid a => [a] -> a
- Numeric.Semigroup: mempty :: Monoid a => a
- Numeric.Semigroup: minMax :: a -> MinMax a
- Numeric.Semigroup: mmAvg :: Fractional a => MinMax a -> a
- Numeric.Semigroup: mmDiff :: Num a => MinMax a -> a
- Numeric.Semigroup: mtimesDefault :: (Integral b, Monoid a) => b -> a -> a
- Numeric.Semigroup: newtype All
- Numeric.Semigroup: newtype Any
- Numeric.Semigroup: newtype Dual a
- Numeric.Semigroup: newtype Endo a
- Numeric.Semigroup: newtype First a
- Numeric.Semigroup: newtype Last a
- Numeric.Semigroup: newtype Max a
- Numeric.Semigroup: newtype Min a
- Numeric.Semigroup: newtype Option a
- Numeric.Semigroup: newtype Product a
- Numeric.Semigroup: newtype Sum a
- Numeric.Semigroup: newtype WrappedMonoid m
- Numeric.Semigroup: option :: b -> (a -> b) -> Option a -> b
- Numeric.Semigroup: sconcat :: Semigroup a => NonEmpty a -> a
- Numeric.Semigroup: stimes :: (Semigroup a, Integral b) => b -> a -> a
- Numeric.Semigroup: stimesIdempotent :: Integral b => b -> a -> a
- Numeric.Semigroup: stimesIdempotentMonoid :: (Integral b, Monoid a) => b -> a -> a
- Numeric.Semigroup: stimesMonoid :: (Integral b, Monoid a) => b -> a -> a
- Numeric.Semigroup: toOption :: a -> Option a
- Numeric.Semigroup: type ArgMax a b = Max Arg a b
- Numeric.Semigroup: type ArgMin a b = Min Arg a b
- Numeric.Vector: unpackV2 :: SubSpace t '[] '[2] '[2] => Vector t 2 -> (t, t)
- Numeric.Vector: unpackV3 :: SubSpace t '[] '[3] '[3] => Vector t 3 -> (t, t, t)
- Numeric.Vector: unpackV4 :: SubSpace t '[] '[4] '[4] => Vector t 4 -> (t, t, t, t)
+ Numeric.DataFrame.Contraction: instance (Data.Type.List.ConcatList as bs asbs, Numeric.Dimensions.Dim.Dimensions as, Numeric.Dimensions.Dim.Dimensions bs, GHC.Num.Num t) => Numeric.DataFrame.Contraction.Contraction t as bs asbs
+ Numeric.DataFrame.IO: copyDataFrame' :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]). (PrimBytes t, PrimBytes (DataFrame t bs), ConcatList as bs asbs) => Idxs as -> DataFrame t bs -> IODataFrame t asbs -> IO ()
+ Numeric.DataFrame.IO: copyMutableDataFrame' :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]). (PrimBytes t, ConcatList as bs asbs) => Idxs as -> IODataFrame t bs -> IODataFrame t asbs -> IO ()
+ Numeric.DataFrame.Internal.Backend: Backend :: backend -> Backend
+ Numeric.DataFrame.Internal.Backend: [_getBackend] :: Backend -> backend
+ Numeric.DataFrame.Internal.Backend: inferBounded :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Bounded t, KnownBackend t ds b) => Dict (Bounded (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferEq :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Eq t, KnownBackend t ds b) => Dict (Eq (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferFloating :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Floating t, KnownBackend t ds b) => Dict (Floating (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferFractional :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Fractional t, KnownBackend t ds b) => Dict (Fractional (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferKnownBackend :: forall (t :: Type) (ds :: [Nat]). (PrimBytes t, Dimensions ds) => Dict (KnownBackend t ds)
+ Numeric.DataFrame.Internal.Backend: inferNum :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Num t, KnownBackend t ds b) => Dict (Num (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferOrd :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Ord t, KnownBackend t ds b) => Dict (Ord (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferPONonTransitive :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Ord t, KnownBackend t ds b) => Dict (Ord (ProductOrd (Backend I t ds b)))
+ Numeric.DataFrame.Internal.Backend: inferPOPartial :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Ord t, KnownBackend t ds b) => Dict (Ord (ProductOrd (Backend I t ds b)))
+ Numeric.DataFrame.Internal.Backend: inferPrimArray :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (PrimBytes t, KnownBackend t ds b) => Dict (PrimArray t (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferPrimBytes :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (PrimBytes t, Dimensions ds, KnownBackend t ds b) => Dict (PrimBytes (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: inferPrimElem :: forall (t :: Type) (d :: Nat) (ds :: [Nat]). KnownBackend t (d : ds) => DFBackend t (d : ds) -> Dict (PrimBytes t)
+ Numeric.DataFrame.Internal.Backend: inferProductOrder :: forall (t :: Type) (ds :: [Nat]) (b :: Type). (Ord t, KnownBackend t ds b) => Dict (ProductOrder (Backend I t ds b))
+ Numeric.DataFrame.Internal.Backend: newtype Backend (i :: Type) (t :: Type) (ds :: [Nat]) (backend :: Type)
+ Numeric.DataFrame.Internal.Backend: type DFBackend (t :: Type) (ds :: [Nat]) = Backend I t ds (BackendFamily t ds)
+ Numeric.DataFrame.Internal.Backend: type KnownBackend (t :: Type) (ds :: [Nat]) = KnownBackend t ds (BackendFamily t ds)
+ Numeric.DataFrame.Internal.Backend: type family BackendFamily (t :: Type) (ds :: [Nat]) = (v :: Type) | v -> t ds
+ Numeric.DataFrame.Internal.Mutable: copyDataFrame'# :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, PrimBytes (DataFrame t bs), ConcatList as bs asbs) => Idxs as -> DataFrame t bs -> MDataFrame s t asbs -> State# s -> (# State# s, () #)
+ Numeric.DataFrame.Internal.Mutable: copyMDataFrame'# :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, ConcatList as bs asbs) => Idxs as -> MDataFrame s t bs -> MDataFrame s t asbs -> State# s -> (# State# s, () #)
+ Numeric.DataFrame.Internal.PrimArray: CumulDims :: [Word] -> CumulDims
+ Numeric.DataFrame.Internal.PrimArray: [unCumulDims] :: CumulDims -> [Word]
+ Numeric.DataFrame.Internal.PrimArray: arrayContent# :: PrimArray t a => a -> (# t | (# CumulDims, Int#, ByteArray# #) #)
+ Numeric.DataFrame.Internal.PrimArray: broadcast :: PrimArray t a => t -> a
+ Numeric.DataFrame.Internal.PrimArray: cdIx :: CumulDims -> Idxs ns -> Int
+ Numeric.DataFrame.Internal.PrimArray: cdTotalDim :: CumulDims -> Word
+ Numeric.DataFrame.Internal.PrimArray: cdTotalDim# :: CumulDims -> Int#
+ Numeric.DataFrame.Internal.PrimArray: class PrimBytes t => PrimArray t a | a -> t
+ Numeric.DataFrame.Internal.PrimArray: cumulDims :: Dims (ns :: [k]) -> CumulDims
+ Numeric.DataFrame.Internal.PrimArray: fromElems :: PrimArray t a => CumulDims -> Int# -> ByteArray# -> a
+ Numeric.DataFrame.Internal.PrimArray: fromSteps :: CumulDims -> SomeDims
+ Numeric.DataFrame.Internal.PrimArray: gen# :: PrimArray t a => CumulDims -> (s -> (# s, t #)) -> s -> (# s, a #)
+ Numeric.DataFrame.Internal.PrimArray: getSteps :: PrimArray t a => Dims (ns :: [k]) -> a -> CumulDims
+ Numeric.DataFrame.Internal.PrimArray: instance GHC.Base.Monoid Numeric.DataFrame.Internal.PrimArray.CumulDims
+ Numeric.DataFrame.Internal.PrimArray: instance GHC.Base.Semigroup Numeric.DataFrame.Internal.PrimArray.CumulDims
+ Numeric.DataFrame.Internal.PrimArray: ix# :: PrimArray t a => Int# -> a -> t
+ Numeric.DataFrame.Internal.PrimArray: ixOff :: PrimArray t a => Int -> a -> t
+ Numeric.DataFrame.Internal.PrimArray: newtype CumulDims
+ Numeric.DataFrame.Internal.PrimArray: offsetElems :: PrimArray t a => a -> Int#
+ Numeric.DataFrame.Internal.PrimArray: uniqueOrCumulDims :: PrimArray t a => a -> Either t CumulDims
+ Numeric.DataFrame.Internal.PrimArray: unsafeFromFlatList :: PrimArray t a => Dims ns -> t -> [t] -> a
+ Numeric.DataFrame.Internal.PrimArray: upd# :: PrimArray t a => CumulDims -> Int# -> t -> a -> a
+ Numeric.DataFrame.ST: copyDataFrame' :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, PrimBytes (DataFrame t bs), ConcatList as bs asbs) => Idxs as -> DataFrame t bs -> STDataFrame s t asbs -> ST s ()
+ Numeric.DataFrame.ST: copyMutableDataFrame' :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, ConcatList as bs asbs) => Idxs as -> STDataFrame s t bs -> STDataFrame s t asbs -> ST s ()
+ Numeric.DataFrame.SubSpace: index :: SubSpace t as bs asbs => Idxs as -> DataFrame t asbs -> DataFrame t bs
+ Numeric.DataFrame.SubSpace: instance (Data.Type.List.ConcatList as bs asbs, Numeric.Dimensions.Dim.Dimensions as, Numeric.Dimensions.Dim.Dimensions bs, Numeric.Dimensions.Dim.Dimensions asbs, Numeric.DataFrame.Internal.PrimArray.PrimArray t (Numeric.DataFrame.Type.DataFrame t bs), Numeric.DataFrame.Internal.PrimArray.PrimArray t (Numeric.DataFrame.Type.DataFrame t asbs), Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Type.DataFrame t bs), Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Type.DataFrame t asbs)) => Numeric.DataFrame.SubSpace.SubSpace t as bs asbs
+ Numeric.DataFrame.SubSpace: slice :: forall (bi :: Nat) (bd :: Nat) (b' :: Nat) (bs' :: [Nat]). (SubSpace t as bs asbs, b' ~ ((bi + bd) - 1), bs ~ (b' :+ bs'), KnownDim bd) => Idxs (as +: bi) -> DataFrame t asbs -> DataFrame t (bd :+ bs')
+ Numeric.DataFrame.SubSpace: updateOffset# :: SubSpace t as bs asbs => Int# -> DataFrame t bs -> DataFrame t asbs -> DataFrame t asbs
+ Numeric.DataFrame.SubSpace: updateSlice :: forall (bi :: Nat) (bd :: Nat) (b' :: Nat) (bs' :: [Nat]). (SubSpace t as bs asbs, b' ~ ((bi + bd) - 1), bs ~ (b' :+ bs'), KnownDim bd) => Idxs (as +: bi) -> DataFrame t (bd :+ bs') -> DataFrame t asbs -> DataFrame t asbs
+ Numeric.DataFrame.Type: appendDF :: forall (n :: Nat) (m :: Nat) (ds :: [Nat]) (t :: Type). (PrimBytes t, Dimensions ds, KnownDim n, KnownDim m) => DataFrame t (n :+ ds) -> DataFrame t (m :+ ds) -> DataFrame t ((n + m) :+ ds)
+ Numeric.DataFrame.Type: bFieldOffsetOf :: forall (name :: Symbol) (a :: Type) (b :: Type). (PrimBytes a, Elem name (PrimFields a), KnownSymbol name, Num b) => a -> b
+ Numeric.DataFrame.Type: class InferKnownBackend (t :: k) ds
+ Numeric.DataFrame.Type: class PrimBytes t => PrimArray t a | a -> t
+ Numeric.DataFrame.Type: class PrimTagged a => PrimBytes a
+ Numeric.DataFrame.Type: consDF :: forall (n :: Nat) (ds :: [Nat]) (t :: Type). (PrimBytes t, Dimensions ds, KnownDim n) => DataFrame t ds -> DataFrame t (n :+ ds) -> DataFrame t ((n + 1) :+ ds)
+ Numeric.DataFrame.Type: constrainDF :: forall (ds :: [XNat]) (ys :: [XNat]) (l :: Type) (ts :: l). (BoundedDims ds, All KnownXNatType ds) => DataFrame ts ys -> Maybe (DataFrame ts ds)
+ Numeric.DataFrame.Type: fromFlatList :: forall (t :: Type) (ds :: [Nat]). PrimArray t (DataFrame t ds) => Dims ds -> t -> [t] -> DataFrame t ds
+ Numeric.DataFrame.Type: fromList :: forall (t :: Type) (ds :: [Nat]). (PrimBytes t, Dimensions ds) => [DataFrame t ds] -> DataFrame t (XN 0 : AsXDims ds)
+ Numeric.DataFrame.Type: fromListWithDefault :: forall (t :: Type) (d :: Nat) (ds :: [Nat]). (PrimBytes t, Dimensions (d : ds)) => DataFrame t ds -> [DataFrame t ds] -> DataFrame t (d : ds)
+ Numeric.DataFrame.Type: inferKnownBackend :: InferKnownBackend t ds => Dict (KnownBackends t ds)
+ Numeric.DataFrame.Type: instance (Data.Data.Data t, Numeric.PrimBytes.PrimBytes t, Data.Typeable.Internal.Typeable ds) => Data.Data.Data (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance (Data.Type.List.All GHC.Read.Read ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts, Numeric.TypedList.RepresentableList ts) => GHC.Read.Read (Numeric.DataFrame.Type.SomeDataFrame ts)
+ Numeric.DataFrame.Type: instance (Data.Type.List.All GHC.Read.Read ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts, Numeric.TypedList.RepresentableList ts, Numeric.Dimensions.Dim.BoundedDims ds, Data.Type.List.All Numeric.Dimensions.Dim.KnownXNatType ds) => GHC.Read.Read (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance (Data.Type.List.All GHC.Read.Read ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts, Numeric.TypedList.RepresentableList ts, Numeric.Dimensions.Dim.Dimensions ds) => GHC.Read.Read (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance (Data.Type.List.All GHC.Show.Show ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts) => GHC.Show.Show (Numeric.DataFrame.Type.DataFrame ts xns)
+ Numeric.DataFrame.Type: instance (Data.Type.List.All GHC.Show.Show ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts) => GHC.Show.Show (Numeric.DataFrame.Type.SomeDataFrame ts)
+ Numeric.DataFrame.Type: instance (Data.Type.List.All GHC.Show.Show ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts, Numeric.Dimensions.Dim.Dimensions ds) => GHC.Show.Show (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance (GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (Numeric.DataFrame.Internal.Backend.DFBackend t ds)), GHC.Classes.Eq (Numeric.DataFrame.Internal.Backend.DFBackend t ds)) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (Numeric.DataFrame.Type.DataFrame t ds))
+ Numeric.DataFrame.Type: instance (GHC.Read.Read t, Numeric.PrimBytes.PrimBytes t) => GHC.Read.Read (Numeric.DataFrame.Type.SomeDataFrame t)
+ Numeric.DataFrame.Type: instance (GHC.Read.Read t, Numeric.PrimBytes.PrimBytes t, Numeric.Dimensions.Dim.BoundedDims ds, Data.Type.List.All Numeric.Dimensions.Dim.KnownXNatType ds) => GHC.Read.Read (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance (GHC.Read.Read t, Numeric.PrimBytes.PrimBytes t, Numeric.Dimensions.Dim.Dimensions ds) => GHC.Read.Read (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance (GHC.Show.Show t, Numeric.PrimBytes.PrimBytes t) => GHC.Show.Show (Numeric.DataFrame.Type.DataFrame t xns)
+ Numeric.DataFrame.Type: instance (GHC.Show.Show t, Numeric.PrimBytes.PrimBytes t) => GHC.Show.Show (Numeric.DataFrame.Type.SomeDataFrame t)
+ Numeric.DataFrame.Type: instance (GHC.Show.Show t, Numeric.PrimBytes.PrimBytes t, Numeric.Dimensions.Dim.Dimensions ds) => GHC.Show.Show (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance (Numeric.DataFrame.Internal.PrimArray.PrimArray t (Numeric.DataFrame.Internal.Backend.DFBackend t ds), Numeric.PrimBytes.PrimBytes t) => Numeric.DataFrame.Internal.PrimArray.PrimArray t (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance (Numeric.DataFrame.Type.AllFrames Data.Data.Data ts ds, Data.Typeable.Internal.Typeable ts, Data.Typeable.Internal.Typeable ds) => Data.Data.Data (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance (Numeric.PrimBytes.PrimBytes t, Numeric.Dimensions.Dim.Dimensions ds) => GHC.Generics.Generic (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance (Numeric.PrimBytes.PrimBytes t, Numeric.Dimensions.Dim.Dimensions ds) => Numeric.DataFrame.Type.InferKnownBackend t ds
+ Numeric.DataFrame.Type: instance (Numeric.TypedList.RepresentableList ts, Data.Type.List.All Numeric.PrimBytes.PrimBytes ts, Numeric.Dimensions.Dim.Dimensions ds) => Numeric.DataFrame.Type.InferKnownBackend ts ds
+ Numeric.DataFrame.Type: instance Data.Type.List.All GHC.Classes.Eq ts => GHC.Classes.Eq (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance Data.Type.List.All GHC.Classes.Eq ts => GHC.Classes.Eq (Numeric.DataFrame.Type.SomeDataFrame ts)
+ Numeric.DataFrame.Type: instance GHC.Classes.Eq (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Classes.Eq (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Classes.Eq t => GHC.Classes.Eq (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Classes.Eq t => GHC.Classes.Eq (Numeric.DataFrame.Type.SomeDataFrame t)
+ Numeric.DataFrame.Type: instance GHC.Classes.Ord (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Classes.Ord (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (Numeric.DataFrame.Internal.Backend.DFBackend t ds)) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (Numeric.DataFrame.Type.DataFrame t ds))
+ Numeric.DataFrame.Type: instance GHC.Enum.Bounded (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Enum.Bounded (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Enum.Enum (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Enum.Enum (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Float.Floating (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Float.Floating (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Float.RealFloat (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Float.RealFloat (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Generics.Generic (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance GHC.Num.Num (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Num.Num (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Real.Fractional (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Real.Fractional (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Real.Integral (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Real.Integral (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Real.Real (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Real.Real (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance GHC.Real.RealFrac (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => GHC.Real.RealFrac (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance Numeric.DataFrame.Type.AllFrames GHC.Classes.Eq ts ds => GHC.Classes.Eq (Numeric.DataFrame.Type.DataFrame ts ds)
+ Numeric.DataFrame.Type: instance Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance Numeric.ProductOrd.ProductOrder (Numeric.DataFrame.Internal.Backend.DFBackend t ds) => Numeric.ProductOrd.ProductOrder (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance forall k l (t :: l) (ds :: [k]). Numeric.PrimBytes.PrimBytes (Numeric.DataFrame.Type.DataFrame t ds) => Foreign.Storable.Storable (Numeric.DataFrame.Type.DataFrame t ds)
+ Numeric.DataFrame.Type: instance forall k l (t :: l) (xs :: [k]). (Data.Data.Data (Numeric.DataFrame.Type.DataFrame t xs), Data.Typeable.Internal.Typeable t, Data.Typeable.Internal.Typeable xs, Data.Typeable.Internal.Typeable k, Data.Typeable.Internal.Typeable l) => Data.Data.Data (Numeric.DataFrame.Type.DataFrame' xs t)
+ Numeric.DataFrame.Type: packDF :: forall (t :: Type) (d :: Nat) (ds :: [Nat]). (PrimBytes t, Dimensions (d : ds)) => PackDF t ds d (DataFrame t (d : ds))
+ Numeric.DataFrame.Type: pattern S :: forall (t :: Type). t -> DataFrame t ('[] :: [Nat])
+ Numeric.DataFrame.Type: snocDF :: forall (n :: Nat) (ds :: [Nat]) (t :: Type). (PrimBytes t, Dimensions ds, KnownDim n) => DataFrame t (n :+ ds) -> DataFrame t ds -> DataFrame t ((n + 1) :+ ds)
+ Numeric.DataFrame.Type: type DFBackend t (ds :: [Nat]) = Backend I t ds BackendFamily t ds
+ Numeric.DataFrame.Type: type KnownBackend t (ds :: [Nat]) = KnownBackend t ds BackendFamily t ds
+ Numeric.DataFrame.Type: type N (n :: Nat) = N n
+ Numeric.DataFrame.Type: type XN (n :: Nat) = XN n
+ Numeric.DataFrame.Type: unpackDF :: forall (t :: Type) (d :: Nat) (ds :: [Nat]) (rep :: RuntimeRep) (r :: TYPE rep). (PrimBytes t, Dimensions (d : ds)) => PackDF t ds d (Dict (Dimensions ds, KnownBackend t ds) -> r) -> DataFrame t (d : ds) -> r
+ Numeric.PrimBytes: --
+ Numeric.PrimBytes: -- </ol>
+ Numeric.PrimBytes: -- <li>The data uses record syntax to define its fields.</li>
+ Numeric.PrimBytes: -- <ol>
+ Numeric.PrimBytes: -- A Generic-derived instance has this list non-empty only if two obvious
+ Numeric.PrimBytes: -- It is used to get field offsets using <a>byteFieldOffset</a> function.
+ Numeric.PrimBytes: -- conditions are met:
+ Numeric.PrimBytes: -- | List of field names.
+ Numeric.PrimBytes: [PTagChar] :: PrimTag Char
+ Numeric.PrimBytes: bAlignOf :: (PrimBytes a, Num b) => a -> b
+ Numeric.PrimBytes: bFieldOffsetOf :: forall (name :: Symbol) (a :: Type) (b :: Type). (PrimBytes a, Elem name (PrimFields a), KnownSymbol name, Num b) => a -> b
+ Numeric.PrimBytes: bPeek :: forall (a :: Type). PrimBytes a => Ptr a -> IO a
+ Numeric.PrimBytes: bPeekByteOff :: forall (a :: Type) (b :: Type). PrimBytes a => Ptr b -> Int -> IO a
+ Numeric.PrimBytes: bPeekElemOff :: forall (a :: Type). PrimBytes a => Ptr a -> Int -> IO a
+ Numeric.PrimBytes: bPoke :: forall (a :: Type). PrimBytes a => Ptr a -> a -> IO ()
+ Numeric.PrimBytes: bPokeByteOff :: forall (a :: Type) (b :: Type). PrimBytes a => Ptr b -> Int -> a -> IO ()
+ Numeric.PrimBytes: bPokeElemOff :: forall (a :: Type). PrimBytes a => Ptr a -> Int -> a -> IO ()
+ Numeric.PrimBytes: bSizeOf :: (PrimBytes a, Num b) => a -> b
+ Numeric.PrimBytes: byteFieldOffset :: (PrimBytes a, Generic a, GPrimBytes (Rep a), KnownSymbol name) => Proxy# name -> a -> Int#
+ Numeric.PrimBytes: getBytesPinned :: PrimBytes a => a -> ByteArray#
+ Numeric.PrimBytes: instance (Numeric.PrimBytes.PrimBytes a, Numeric.PrimBytes.PrimBytes b) => Numeric.PrimBytes.PrimBytes (a, b)
+ Numeric.PrimBytes: instance (Numeric.PrimBytes.PrimBytes a, Numeric.PrimBytes.PrimBytes b, Numeric.PrimBytes.PrimBytes c) => Numeric.PrimBytes.PrimBytes (a, b, c)
+ Numeric.PrimBytes: instance (Numeric.PrimBytes.PrimBytes a, Numeric.PrimBytes.PrimBytes b, Numeric.PrimBytes.PrimBytes c, Numeric.PrimBytes.PrimBytes d) => Numeric.PrimBytes.PrimBytes (a, b, c, d)
+ Numeric.PrimBytes: instance (Numeric.PrimBytes.PrimBytes a, Numeric.PrimBytes.PrimBytes b, Numeric.PrimBytes.PrimBytes c, Numeric.PrimBytes.PrimBytes d, Numeric.PrimBytes.PrimBytes e) => Numeric.PrimBytes.PrimBytes (a, b, c, d, e)
+ Numeric.PrimBytes: instance (Numeric.PrimBytes.PrimBytes a, Numeric.PrimBytes.PrimBytes b, Numeric.PrimBytes.PrimBytes c, Numeric.PrimBytes.PrimBytes d, Numeric.PrimBytes.PrimBytes e, Numeric.PrimBytes.PrimBytes f) => Numeric.PrimBytes.PrimBytes (a, b, c, d, e, f)
+ Numeric.PrimBytes: instance (Numeric.PrimBytes.PrimBytes a, Numeric.PrimBytes.PrimBytes b, Numeric.PrimBytes.PrimBytes c, Numeric.PrimBytes.PrimBytes d, Numeric.PrimBytes.PrimBytes e, Numeric.PrimBytes.PrimBytes f, Numeric.PrimBytes.PrimBytes g) => Numeric.PrimBytes.PrimBytes (a, b, c, d, e, f, g)
+ Numeric.PrimBytes: instance (Numeric.TypedList.RepresentableList xs, Data.Type.List.All Numeric.PrimBytes.PrimBytes xs) => Numeric.PrimBytes.PrimBytes (Numeric.Tuple.Lazy.Tuple xs)
+ Numeric.PrimBytes: instance (Numeric.TypedList.RepresentableList xs, Data.Type.List.All Numeric.PrimBytes.PrimBytes xs) => Numeric.PrimBytes.PrimBytes (Numeric.Tuple.Strict.Tuple xs)
+ Numeric.PrimBytes: instance GHC.Show.Show (Numeric.PrimBytes.PrimTag a)
+ Numeric.PrimBytes: instance Numeric.PrimBytes.PrimBytes ()
+ Numeric.PrimBytes: instance Numeric.PrimBytes.PrimBytes GHC.Types.Char
+ Numeric.PrimBytes: instance Numeric.PrimBytes.PrimTagged GHC.Types.Char
+ Numeric.PrimBytes: instance forall k (f :: k -> *) (g :: k -> *). (Numeric.PrimBytes.GPrimBytes f, Numeric.PrimBytes.GPrimBytes g) => Numeric.PrimBytes.GPrimBytes (f GHC.Generics.:*: g)
+ Numeric.PrimBytes: instance forall k (f :: k -> *) (g :: k -> *). (Numeric.PrimBytes.GPrimBytes f, Numeric.PrimBytes.GPrimBytes g) => Numeric.PrimBytes.GPrimBytes (f GHC.Generics.:+: g)
+ Numeric.PrimBytes: instance forall k (f :: k -> *) (sn :: GHC.Types.Symbol) (a :: GHC.Generics.SourceUnpackedness) (b :: GHC.Generics.SourceStrictness) (c :: GHC.Generics.DecidedStrictness). (Numeric.PrimBytes.GPrimBytes f, GHC.TypeLits.KnownSymbol sn) => Numeric.PrimBytes.GPrimBytes (GHC.Generics.M1 GHC.Generics.S ('GHC.Generics.MetaSel ('GHC.Maybe.Just sn) a b c) f)
+ Numeric.PrimBytes: instance forall k (f :: k -> *) i (c :: GHC.Generics.Meta). Numeric.PrimBytes.GPrimBytes f => Numeric.PrimBytes.GPrimBytes (GHC.Generics.M1 i c f)
+ Numeric.PrimBytes: instance forall k (x :: k). Numeric.PrimBytes.PrimBytes (Numeric.Dimensions.Idx.Idx x)
+ Numeric.PrimBytes: instance forall k (xs :: [k]). Numeric.TypedList.RepresentableList xs => Numeric.PrimBytes.PrimBytes (Numeric.Dimensions.Idx.Idxs xs)
+ Numeric.PrimBytes: type PrimFields a = GPrimFields (Rep a);
+ Numeric.PrimBytes: type family PrimFields a :: [Symbol];
+ Numeric.PrimBytes: }
+ Numeric.ProductOrd: Incomparable :: PartialOrdering
+ Numeric.ProductOrd: PEQ :: PartialOrdering
+ Numeric.ProductOrd: PGT :: PartialOrdering
+ Numeric.ProductOrd: PLT :: PartialOrdering
+ Numeric.ProductOrd: class ProductOrder a
+ Numeric.ProductOrd: cmp :: ProductOrder a => a -> a -> PartialOrdering
+ Numeric.ProductOrd: data PartialOrdering
+ Numeric.ProductOrd: fromOrdering :: Ordering -> PartialOrdering
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2) => Numeric.ProductOrd.ProductOrder (a1, a2)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3) => Numeric.ProductOrd.ProductOrder (a1, a2, a3)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4) => Numeric.ProductOrd.ProductOrder (a1, a2, a3, a4)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5) => Numeric.ProductOrd.ProductOrder (a1, a2, a3, a4, a5)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6) => Numeric.ProductOrd.ProductOrder (a1, a2, a3, a4, a5, a6)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7) => Numeric.ProductOrd.ProductOrder (a1, a2, a3, a4, a5, a6, a7)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7, GHC.Classes.Ord a8) => Numeric.ProductOrd.ProductOrder (a1, a2, a3, a4, a5, a6, a7, a8)
+ Numeric.ProductOrd: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7, GHC.Classes.Ord a8, GHC.Classes.Ord a9) => Numeric.ProductOrd.ProductOrder (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+ Numeric.ProductOrd: instance Data.Data.Data Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Base.Monoid Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Base.Semigroup Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Classes.Eq Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Classes.Ord Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Enum.Bounded Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Enum.Enum Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Generics.Generic Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Read.Read Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance GHC.Show.Show Numeric.ProductOrd.PartialOrdering
+ Numeric.ProductOrd: instance forall k (f :: k -> *) (xs :: [k]). Data.Type.List.All GHC.Classes.Ord (Data.Type.List.Map f xs) => Numeric.ProductOrd.ProductOrder (Numeric.TypedList.TypedList f xs)
+ Numeric.ProductOrd.NonTransitive: ProductOrd :: a -> ProductOrd a
+ Numeric.ProductOrd.NonTransitive: [getProductOrd] :: ProductOrd a -> a
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a), Data.Bits.Bits a) => Data.Bits.Bits (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a), Data.Bits.FiniteBits a) => Data.Bits.FiniteBits (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a), GHC.Float.RealFloat a) => GHC.Float.RealFloat (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a), GHC.Real.Integral a) => GHC.Real.Integral (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a), GHC.Real.Real a) => GHC.Real.Real (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a), GHC.Real.RealFrac a) => GHC.Real.RealFrac (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3, a4))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3, a4, a5))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3, a4, a5, a6))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3, a4, a5, a6, a7))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7, GHC.Classes.Ord a8) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8))
+ Numeric.ProductOrd.NonTransitive: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7, GHC.Classes.Ord a8, GHC.Classes.Ord a9) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9))
+ Numeric.ProductOrd.NonTransitive: instance Control.Monad.Fix.MonadFix Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance Control.Monad.Zip.MonadZip Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance Data.Data.Data a => Data.Data.Data (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance Data.Foldable.Foldable Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance Data.Traversable.Traversable Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Base.Applicative Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance GHC.Base.Functor Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance GHC.Base.Monad Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance GHC.Base.Monoid a => GHC.Base.Monoid (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd a) => GHC.Classes.Eq (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Enum.Enum a => GHC.Enum.Enum (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Float.Floating a => GHC.Float.Floating (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Generics.Generic (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Generics.Generic1 Numeric.ProductOrd.NonTransitive.ProductOrd
+ Numeric.ProductOrd.NonTransitive: instance GHC.Num.Num a => GHC.Num.Num (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Read.Read a => GHC.Read.Read (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Real.Fractional a => GHC.Real.Fractional (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance GHC.Show.Show a => GHC.Show.Show (Numeric.ProductOrd.NonTransitive.ProductOrd a)
+ Numeric.ProductOrd.NonTransitive: instance forall k (f :: k -> *) (xs :: [k]). Data.Type.List.All GHC.Classes.Ord (Data.Type.List.Map f xs) => GHC.Classes.Ord (Numeric.ProductOrd.NonTransitive.ProductOrd (Numeric.TypedList.TypedList f xs))
+ Numeric.ProductOrd.NonTransitive: newtype ProductOrd a
+ Numeric.ProductOrd.NonTransitive: toOrdering :: PartialOrdering -> Ordering
+ Numeric.ProductOrd.Partial: ProductOrd :: a -> ProductOrd a
+ Numeric.ProductOrd.Partial: [getProductOrd] :: ProductOrd a -> a
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd a), GHC.Float.RealFloat a) => GHC.Float.RealFloat (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd a), GHC.Real.Integral a) => GHC.Real.Integral (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd a), GHC.Real.Real a) => GHC.Real.Real (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd a), GHC.Real.RealFrac a) => GHC.Real.RealFrac (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3, a4))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3, a4, a5))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3, a4, a5, a6))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3, a4, a5, a6, a7))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7, GHC.Classes.Ord a8) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8))
+ Numeric.ProductOrd.Partial: instance (GHC.Classes.Ord a1, GHC.Classes.Ord a2, GHC.Classes.Ord a3, GHC.Classes.Ord a4, GHC.Classes.Ord a5, GHC.Classes.Ord a6, GHC.Classes.Ord a7, GHC.Classes.Ord a8, GHC.Classes.Ord a9) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9))
+ Numeric.ProductOrd.Partial: instance Control.Monad.Fix.MonadFix Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance Control.Monad.Zip.MonadZip Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance Data.Bits.Bits a => Data.Bits.Bits (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance Data.Bits.FiniteBits a => Data.Bits.FiniteBits (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance Data.Data.Data a => Data.Data.Data (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance Data.Foldable.Foldable Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance Data.Traversable.Traversable Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Base.Applicative Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance GHC.Base.Functor Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance GHC.Base.Monad Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance GHC.Base.Monoid a => GHC.Base.Monoid (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Classes.Eq a => GHC.Classes.Eq (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Enum.Enum a => GHC.Enum.Enum (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Float.Floating a => GHC.Float.Floating (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Generics.Generic (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Generics.Generic1 Numeric.ProductOrd.Partial.ProductOrd
+ Numeric.ProductOrd.Partial: instance GHC.Num.Num a => GHC.Num.Num (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Read.Read a => GHC.Read.Read (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Real.Fractional a => GHC.Real.Fractional (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance GHC.Show.Show a => GHC.Show.Show (Numeric.ProductOrd.Partial.ProductOrd a)
+ Numeric.ProductOrd.Partial: instance forall k (f :: k -> *) (xs :: [k]). Data.Type.List.All GHC.Classes.Ord (Data.Type.List.Map f xs) => GHC.Classes.Eq (Numeric.ProductOrd.Partial.ProductOrd (Numeric.TypedList.TypedList f xs))
+ Numeric.ProductOrd.Partial: instance forall k (f :: k -> *) (xs :: [k]). Data.Type.List.All GHC.Classes.Ord (Data.Type.List.Map f xs) => GHC.Classes.Ord (Numeric.ProductOrd.Partial.ProductOrd (Numeric.TypedList.TypedList f xs))
+ Numeric.ProductOrd.Partial: newtype ProductOrd a
+ Numeric.ProductOrd.Partial: toOrdering :: PartialOrdering -> Ordering
+ Numeric.Quaternion: -- <tt>(x,y,z,w)</tt>, where <tt>w</tt> is the argument, and <tt>x y
+ Numeric.Quaternion: -- z</tt> are the components of a 3D vector
+ Numeric.Quaternion: unpackQ# :: Quaternion t => Quater t -> (# t, t, t, t #)
+ Numeric.Vector: class Vector2 t
+ Numeric.Vector: class Vector3 t
+ Numeric.Vector: class Vector4 t
+ Numeric.Vector: data family DataFrame (t :: l) (xs :: [k])
+ Numeric.Vector: pattern Vec4 :: Vector4 t => t -> t -> t -> t -> Vector t 4
+ Numeric.Vector: unpackV2# :: Vector2 t => Vector t 2 -> (# t, t #)
+ Numeric.Vector: unpackV3# :: Vector3 t => Vector t 3 -> (# t, t, t #)
+ Numeric.Vector: unpackV4# :: Vector4 t => Vector t 4 -> (# t, t, t, t #)
- Numeric.DataFrame.Contraction: (%*) :: (ConcatList as bs (as ++ bs), Contraction t as bs asbs, KnownDim m, PrimArray t (DataFrame t (as +: m)), PrimArray t (DataFrame t (m :+ bs)), PrimArray t (DataFrame t (as ++ bs))) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t (as ++ bs)
+ Numeric.DataFrame.Contraction: (%*) :: (Contraction t as bs asbs, KnownDim m, PrimArray t (DataFrame t (as +: m)), PrimArray t (DataFrame t (m :+ bs)), PrimArray t (DataFrame t asbs)) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t asbs
- Numeric.DataFrame.IO: copyDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat) (bs :: [Nat]) (asbs :: [Nat]). (PrimBytes t, PrimBytes (DataFrame t (as +: b')), ConcatList as (b :+ bs) asbs, Dimensions (b :+ bs)) => DataFrame t (as +: b') -> Idxs (b :+ bs) -> IODataFrame t asbs -> IO ()
+ Numeric.DataFrame.IO: copyDataFrame :: forall (t :: Type) (b :: Nat) (bi :: Nat) (bd :: Nat) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]). (b ~ ((bi + bd) - 1), PrimBytes t, PrimBytes (DataFrame t (bd :+ bs)), ConcatList as (b :+ bs) asbs) => Idxs (as +: bi) -> DataFrame t (bd :+ bs) -> IODataFrame t asbs -> IO ()
- Numeric.DataFrame.IO: copyMutableDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat) (bs :: [Nat]) (asbs :: [Nat]). (PrimBytes t, ConcatList as (b :+ bs) asbs, Dimensions (b :+ bs)) => IODataFrame t (as +: b') -> Idxs (b :+ bs) -> IODataFrame t asbs -> IO ()
+ Numeric.DataFrame.IO: copyMutableDataFrame :: forall (t :: Type) (b :: Nat) (bi :: Nat) (bd :: Nat) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]). (b ~ ((bi + bd) - 1), PrimBytes t, ConcatList as (b :+ bs) asbs) => Idxs (as +: bi) -> IODataFrame t (bd :+ bs) -> IODataFrame t asbs -> IO ()
- Numeric.DataFrame.IO: isDataFramePinned :: forall (t :: Type) (ns :: [k]). KnownDimKind k => IODataFrame t ns -> Bool
+ Numeric.DataFrame.IO: isDataFramePinned :: forall (k :: Type) (t :: Type) (ns :: [k]). KnownDimKind k => IODataFrame t ns -> Bool
- Numeric.DataFrame.IO: readDataFrame :: forall (t :: Type) (ns :: [Nat]). (PrimBytes t, Dimensions ns) => IODataFrame t ns -> Idxs ns -> IO (DataFrame t ('[] :: [Nat]))
+ Numeric.DataFrame.IO: readDataFrame :: forall (t :: Type) (ns :: [Nat]). PrimBytes t => IODataFrame t ns -> Idxs ns -> IO (DataFrame t ('[] :: [Nat]))
- Numeric.DataFrame.IO: thawDataFrame :: forall (t :: Type) (ns :: [Nat]). (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> IO (IODataFrame t ns)
+ Numeric.DataFrame.IO: thawDataFrame :: forall (t :: Type) (ns :: [Nat]). (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> IO (IODataFrame t ns)
- Numeric.DataFrame.IO: thawPinDataFrame :: forall (t :: Type) (ns :: [Nat]). (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> IO (IODataFrame t ns)
+ Numeric.DataFrame.IO: thawPinDataFrame :: forall (t :: Type) (ns :: [Nat]). (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> IO (IODataFrame t ns)
- Numeric.DataFrame.IO: unsafeThawDataFrame :: forall (t :: Type) (ns :: [Nat]). (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> IO (IODataFrame t ns)
+ Numeric.DataFrame.IO: unsafeThawDataFrame :: forall (t :: Type) (ns :: [Nat]). (Dimensions ns, PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> IO (IODataFrame t ns)
- Numeric.DataFrame.IO: withDataFramePtr :: forall (t :: Type) (ns :: [k]) (r :: Type). (PrimBytes t, KnownDimKind k) => IODataFrame t ns -> (Ptr t -> IO r) -> IO r
+ Numeric.DataFrame.IO: withDataFramePtr :: forall (k :: Type) (t :: Type) (ns :: [k]) (r :: Type). (PrimBytes t, KnownDimKind k) => IODataFrame t ns -> (Ptr t -> IO r) -> IO r
- Numeric.DataFrame.IO: writeDataFrame :: forall t (ns :: [Nat]). (PrimBytes t, Dimensions ns) => IODataFrame t ns -> Idxs ns -> DataFrame t ('[] :: [Nat]) -> IO ()
+ Numeric.DataFrame.IO: writeDataFrame :: forall t (ns :: [Nat]). PrimBytes t => IODataFrame t ns -> Idxs ns -> DataFrame t ('[] :: [Nat]) -> IO ()
- Numeric.DataFrame.Internal.Mutable: copyDataFrame# :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, PrimBytes (DataFrame t (as +: b')), ConcatList as (b :+ bs) asbs, Dimensions (b :+ bs)) => DataFrame t (as +: b') -> Idxs (b :+ bs) -> MDataFrame s t asbs -> State# s -> (# State# s, () #)
+ Numeric.DataFrame.Internal.Mutable: copyDataFrame# :: forall (t :: Type) (b :: Nat) (bi :: Nat) (bd :: Nat) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (b ~ ((bi + bd) - 1), PrimBytes t, PrimBytes (DataFrame t (bd :+ bs)), ConcatList as (b :+ bs) asbs) => Idxs (as +: bi) -> DataFrame t (bd :+ bs) -> MDataFrame s t asbs -> State# s -> (# State# s, () #)
- Numeric.DataFrame.Internal.Mutable: copyMDataFrame# :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, ConcatList as (b :+ bs) asbs, Dimensions (b :+ bs)) => MDataFrame s t (as +: b') -> Idxs (b :+ bs) -> MDataFrame s t asbs -> State# s -> (# State# s, () #)
+ Numeric.DataFrame.Internal.Mutable: copyMDataFrame# :: forall (t :: Type) (b :: Nat) (bi :: Nat) (bd :: Nat) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (b ~ ((bi + bd) - 1), PrimBytes t, ConcatList as (b :+ bs) asbs) => Idxs (as +: bi) -> MDataFrame s t (bd :+ bs) -> MDataFrame s t asbs -> State# s -> (# State# s, () #)
- Numeric.DataFrame.Internal.Mutable: readDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes t, Dimensions ns) => MDataFrame s t ns -> Idxs ns -> State# s -> (# State# s, t #)
+ Numeric.DataFrame.Internal.Mutable: readDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. PrimBytes t => MDataFrame s t ns -> Idxs ns -> State# s -> (# State# s, t #)
- Numeric.DataFrame.Internal.Mutable: thawDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #)
+ Numeric.DataFrame.Internal.Mutable: thawDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #)
- Numeric.DataFrame.Internal.Mutable: thawPinDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #)
+ Numeric.DataFrame.Internal.Mutable: thawPinDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #)
- Numeric.DataFrame.Internal.Mutable: unsafeThawDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #)
+ Numeric.DataFrame.Internal.Mutable: unsafeThawDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (Dimensions ns, PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #)
- Numeric.DataFrame.Internal.Mutable: writeDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes t, Dimensions ns) => MDataFrame s t ns -> Idxs ns -> t -> State# s -> (# State# s, () #)
+ Numeric.DataFrame.Internal.Mutable: writeDataFrame# :: forall (t :: Type) (ns :: [Nat]) s. PrimBytes t => MDataFrame s t ns -> Idxs ns -> t -> State# s -> (# State# s, () #)
- Numeric.DataFrame.ST: copyDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, PrimBytes (DataFrame t (as +: b')), ConcatList as (b :+ bs) asbs, Dimensions (b :+ bs)) => DataFrame t (as +: b') -> Idxs (b :+ bs) -> STDataFrame s t asbs -> ST s ()
+ Numeric.DataFrame.ST: copyDataFrame :: forall (t :: Type) (b :: Nat) (bi :: Nat) (bd :: Nat) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (b ~ ((bi + bd) - 1), PrimBytes t, PrimBytes (DataFrame t (bd :+ bs)), ConcatList as (b :+ bs) asbs) => Idxs (as +: bi) -> DataFrame t (bd :+ bs) -> STDataFrame s t asbs -> ST s ()
- Numeric.DataFrame.ST: copyMutableDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat) (bs :: [Nat]) (asbs :: [Nat]) s. (PrimBytes t, ConcatList as (b :+ bs) asbs, Dimensions (b :+ bs)) => STDataFrame s t (as +: b') -> Idxs (b :+ bs) -> STDataFrame s t asbs -> ST s ()
+ Numeric.DataFrame.ST: copyMutableDataFrame :: forall (t :: Type) (b :: Nat) (bi :: Nat) (bd :: Nat) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s. (b ~ ((bi + bd) - 1), PrimBytes t, ConcatList as (b :+ bs) asbs) => Idxs (as +: bi) -> STDataFrame s t (bd :+ bs) -> STDataFrame s t asbs -> ST s ()
- Numeric.DataFrame.ST: isDataFramePinned :: forall (t :: Type) (ns :: [k]) s. KnownDimKind k => STDataFrame s t ns -> Bool
+ Numeric.DataFrame.ST: isDataFramePinned :: forall (k :: Type) (t :: Type) (ns :: [k]) s. KnownDimKind k => STDataFrame s t ns -> Bool
- Numeric.DataFrame.ST: readDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes t, Dimensions ns) => STDataFrame s t ns -> Idxs ns -> ST s (DataFrame t ('[] :: [Nat]))
+ Numeric.DataFrame.ST: readDataFrame :: forall (t :: Type) (ns :: [Nat]) s. PrimBytes t => STDataFrame s t ns -> Idxs ns -> ST s (DataFrame t ('[] :: [Nat]))
- Numeric.DataFrame.ST: thawDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> ST s (STDataFrame s t ns)
+ Numeric.DataFrame.ST: thawDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> ST s (STDataFrame s t ns)
- Numeric.DataFrame.ST: thawPinDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> ST s (STDataFrame s t ns)
+ Numeric.DataFrame.ST: thawPinDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> ST s (STDataFrame s t ns)
- Numeric.DataFrame.ST: unsafeThawDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> ST s (STDataFrame s t ns)
+ Numeric.DataFrame.ST: unsafeThawDataFrame :: forall (t :: Type) (ns :: [Nat]) s. (Dimensions ns, PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> ST s (STDataFrame s t ns)
- Numeric.DataFrame.ST: writeDataFrame :: forall t (ns :: [Nat]) s. (PrimBytes t, Dimensions ns) => STDataFrame s t ns -> Idxs ns -> DataFrame t ('[] :: [Nat]) -> ST s ()
+ Numeric.DataFrame.ST: writeDataFrame :: forall t (ns :: [Nat]) s. PrimBytes t => STDataFrame s t ns -> Idxs ns -> DataFrame t ('[] :: [Nat]) -> ST s ()
- Numeric.DataFrame.SubSpace: (!) :: SubSpace t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) => DataFrame t asbs -> Idxs bs -> DataFrame t as
+ Numeric.DataFrame.SubSpace: (!) :: SubSpace t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) => DataFrame t asbs -> Idxs as -> DataFrame t bs
- Numeric.DataFrame.SubSpace: class (ConcatList as bs asbs, Dimensions as, Dimensions bs, Dimensions asbs, PrimArray t (DataFrame t asbs)) => SubSpace (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) | asbs as -> bs, asbs bs -> as, as bs -> asbs
+ Numeric.DataFrame.SubSpace: class (ConcatList as bs asbs, Dimensions as, Dimensions bs, Dimensions asbs, PrimArray t (DataFrame t bs), PrimArray t (DataFrame t asbs), PrimBytes (DataFrame t bs), PrimBytes (DataFrame t asbs)) => SubSpace (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) | asbs as -> bs, asbs bs -> as, as bs -> asbs
- Numeric.DataFrame.SubSpace: element :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) f. (SubSpace t as bs asbs, Applicative f) => Idxs bs -> (DataFrame t as -> f (DataFrame t as)) -> DataFrame t asbs -> f (DataFrame t asbs)
+ Numeric.DataFrame.SubSpace: element :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) f. (SubSpace t as bs asbs, Applicative f) => Idxs as -> (DataFrame t bs -> f (DataFrame t bs)) -> DataFrame t asbs -> f (DataFrame t asbs)
- Numeric.DataFrame.SubSpace: elementWise :: forall s (as' :: [Nat]) (asbs' :: [Nat]) f. (SubSpace t as bs asbs, Applicative f, SubSpace s as' bs asbs') => (DataFrame s as' -> f (DataFrame t as)) -> DataFrame s asbs' -> f (DataFrame t asbs)
+ Numeric.DataFrame.SubSpace: elementWise :: forall (s :: Type) (bs' :: [Nat]) (asbs' :: [Nat]) (f :: Type -> Type). (SubSpace t as bs asbs, Applicative f, SubSpace s as bs' asbs') => (DataFrame s bs' -> f (DataFrame t bs)) -> DataFrame s asbs' -> f (DataFrame t asbs)
- Numeric.DataFrame.SubSpace: elementWise_ :: forall t as bs asbs f b. (SubSpace t as bs asbs, Applicative f) => (DataFrame t as -> f b) -> DataFrame t asbs -> f ()
+ Numeric.DataFrame.SubSpace: elementWise_ :: forall t as bs asbs f b. (SubSpace t as bs asbs, Applicative f) => (DataFrame t bs -> f b) -> DataFrame t asbs -> f ()
- Numeric.DataFrame.SubSpace: ewfoldMap :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) m. (Monoid m, SubSpace t as bs asbs) => (DataFrame t as -> m) -> DataFrame t asbs -> m
+ Numeric.DataFrame.SubSpace: ewfoldMap :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) m. (Monoid m, SubSpace t as bs asbs) => (DataFrame t bs -> m) -> DataFrame t asbs -> m
- Numeric.DataFrame.SubSpace: ewfoldl :: SubSpace t as bs asbs => (b -> DataFrame t as -> b) -> b -> DataFrame t asbs -> b
+ Numeric.DataFrame.SubSpace: ewfoldl :: SubSpace t as bs asbs => (b -> DataFrame t bs -> b) -> b -> DataFrame t asbs -> b
- Numeric.DataFrame.SubSpace: ewfoldr :: SubSpace t as bs asbs => (DataFrame t as -> b -> b) -> b -> DataFrame t asbs -> b
+ Numeric.DataFrame.SubSpace: ewfoldr :: SubSpace t as bs asbs => (DataFrame t bs -> b -> b) -> b -> DataFrame t asbs -> b
- Numeric.DataFrame.SubSpace: ewgen :: SubSpace t as bs asbs => DataFrame t as -> DataFrame t asbs
+ Numeric.DataFrame.SubSpace: ewgen :: SubSpace t as bs asbs => DataFrame t bs -> DataFrame t asbs
- Numeric.DataFrame.SubSpace: ewmap :: forall s (as' :: [Nat]) (asbs' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as' bs asbs') => (DataFrame s as' -> DataFrame t as) -> DataFrame s asbs' -> DataFrame t asbs
+ Numeric.DataFrame.SubSpace: ewmap :: forall s (bs' :: [Nat]) (asbs' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as bs' asbs') => (DataFrame s bs' -> DataFrame t bs) -> DataFrame s asbs' -> DataFrame t asbs
- Numeric.DataFrame.SubSpace: ewzip :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s (as' :: [Nat]) (asbs' :: [Nat]) r (as'' :: [Nat]) (asbs'' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as' bs asbs', SubSpace r as'' bs asbs'') => (DataFrame t as -> DataFrame s as' -> DataFrame r as'') -> DataFrame t asbs -> DataFrame s asbs' -> DataFrame r asbs''
+ Numeric.DataFrame.SubSpace: ewzip :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s (bs' :: [Nat]) (asbs' :: [Nat]) r (bs'' :: [Nat]) (asbs'' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as bs' asbs', SubSpace r as bs'' asbs'') => (DataFrame t bs -> DataFrame s bs' -> DataFrame r bs'') -> DataFrame t asbs -> DataFrame s asbs' -> DataFrame r asbs''
- Numeric.DataFrame.SubSpace: indexOffset# :: SubSpace t as bs asbs => Int# -> Int# -> DataFrame t asbs -> DataFrame t as
+ Numeric.DataFrame.SubSpace: indexOffset# :: SubSpace t as bs asbs => Int# -> DataFrame t asbs -> DataFrame t bs
- Numeric.DataFrame.SubSpace: indexWise :: forall s (as' :: [Nat]) (asbs' :: [Nat]) f. (SubSpace t as bs asbs, Applicative f, SubSpace s as' bs asbs') => (Idxs bs -> DataFrame s as' -> f (DataFrame t as)) -> DataFrame s asbs' -> f (DataFrame t asbs)
+ Numeric.DataFrame.SubSpace: indexWise :: forall (s :: Type) (bs' :: [Nat]) (asbs' :: [Nat]) (f :: Type -> Type). (SubSpace t as bs asbs, Applicative f, SubSpace s as bs' asbs') => (Idxs as -> DataFrame s bs' -> f (DataFrame t bs)) -> DataFrame s asbs' -> f (DataFrame t asbs)
- Numeric.DataFrame.SubSpace: indexWise_ :: forall t as bs asbs f b. (SubSpace t as bs asbs, Applicative f) => (Idxs bs -> DataFrame t as -> f b) -> DataFrame t asbs -> f ()
+ Numeric.DataFrame.SubSpace: indexWise_ :: forall t as bs asbs f b. (SubSpace t as bs asbs, Applicative f) => (Idxs as -> DataFrame t bs -> f b) -> DataFrame t asbs -> f ()
- Numeric.DataFrame.SubSpace: iwfoldMap :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) m. (Monoid m, SubSpace t as bs asbs) => (Idxs bs -> DataFrame t as -> m) -> DataFrame t asbs -> m
+ Numeric.DataFrame.SubSpace: iwfoldMap :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) m. (Monoid m, SubSpace t as bs asbs) => (Idxs as -> DataFrame t bs -> m) -> DataFrame t asbs -> m
- Numeric.DataFrame.SubSpace: iwfoldl :: SubSpace t as bs asbs => (Idxs bs -> b -> DataFrame t as -> b) -> b -> DataFrame t asbs -> b
+ Numeric.DataFrame.SubSpace: iwfoldl :: SubSpace t as bs asbs => (Idxs as -> b -> DataFrame t bs -> b) -> b -> DataFrame t asbs -> b
- Numeric.DataFrame.SubSpace: iwfoldr :: SubSpace t as bs asbs => (Idxs bs -> DataFrame t as -> b -> b) -> b -> DataFrame t asbs -> b
+ Numeric.DataFrame.SubSpace: iwfoldr :: SubSpace t as bs asbs => (Idxs as -> DataFrame t bs -> b -> b) -> b -> DataFrame t asbs -> b
- Numeric.DataFrame.SubSpace: iwgen :: SubSpace t as bs asbs => (Idxs bs -> DataFrame t as) -> DataFrame t asbs
+ Numeric.DataFrame.SubSpace: iwgen :: SubSpace t as bs asbs => (Idxs as -> DataFrame t bs) -> DataFrame t asbs
- Numeric.DataFrame.SubSpace: iwmap :: forall s (as' :: [Nat]) (asbs' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as' bs asbs') => (Idxs bs -> DataFrame s as' -> DataFrame t as) -> DataFrame s asbs' -> DataFrame t asbs
+ Numeric.DataFrame.SubSpace: iwmap :: forall s (bs' :: [Nat]) (asbs' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as bs' asbs') => (Idxs as -> DataFrame s bs' -> DataFrame t bs) -> DataFrame s asbs' -> DataFrame t asbs
- Numeric.DataFrame.SubSpace: iwzip :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s (as' :: [Nat]) (asbs' :: [Nat]) r (as'' :: [Nat]) (asbs'' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as' bs asbs', SubSpace r as'' bs asbs'') => (Idxs bs -> DataFrame t as -> DataFrame s as' -> DataFrame r as'') -> DataFrame t asbs -> DataFrame s asbs' -> DataFrame r asbs''
+ Numeric.DataFrame.SubSpace: iwzip :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s (bs' :: [Nat]) (asbs' :: [Nat]) r (bs'' :: [Nat]) (asbs'' :: [Nat]). (SubSpace t as bs asbs, SubSpace s as bs' asbs', SubSpace r as bs'' asbs'') => (Idxs as -> DataFrame t bs -> DataFrame s bs' -> DataFrame r bs'') -> DataFrame t asbs -> DataFrame s asbs' -> DataFrame r asbs''
- Numeric.DataFrame.SubSpace: update :: SubSpace t as bs asbs => Idxs bs -> DataFrame t as -> DataFrame t asbs -> DataFrame t asbs
+ Numeric.DataFrame.SubSpace: update :: SubSpace t as bs asbs => Idxs as -> DataFrame t bs -> DataFrame t asbs -> DataFrame t asbs
- Numeric.DataFrame.Type: bAlignOf :: PrimBytes a => a -> Int
+ Numeric.DataFrame.Type: bAlignOf :: (PrimBytes a, Num b) => a -> b
- Numeric.DataFrame.Type: bSizeOf :: PrimBytes a => a -> Int
+ Numeric.DataFrame.Type: bSizeOf :: (PrimBytes a, Num b) => a -> b
- Numeric.DataFrame.Type: inferPrimElem :: (DataFrameInference t, ArraySingletons t ds, ds ~ (Head ds : Tail ds)) => DataFrame t ds -> Evidence (AllTypes PrimBytes t)
+ Numeric.DataFrame.Type: inferPrimElem :: forall (t :: Type) (d :: Nat) (ds :: [Nat]). KnownBackend t (d : ds) => DataFrame t (d : ds) -> Dict (PrimBytes t)
- Numeric.DataFrame.Type: pattern Z :: forall (xs :: [Type]) (ns :: [Nat]). () => xs ~ '[] => DataFrame xs ns
+ Numeric.DataFrame.Type: pattern DF9 :: forall (t :: Type) (ds :: [Nat]). (PrimBytes t, Dimensions (9 : ds)) => (Dimensions ds, KnownBackend t ds) => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t (9 : ds)
- Numeric.DataFrame.Type: pattern KnownDims :: forall k (ds :: [k]). () => (All (KnownDim :: k -> Constraint) ds, Dimensions ds) => Dims ds
+ Numeric.DataFrame.Type: pattern KnownDims :: forall (ds :: [Nat]). () => (All KnownDim ds, All (BoundedDim :: Nat -> Constraint) ds, RepresentableList ds, Dimensions ds) => Dims ds
- Numeric.DataFrame.Type: type family PrimFrames (ts :: l) (ns :: [Nat]) :: Constraint
+ Numeric.DataFrame.Type: type family KnownBackends (ts :: l) (ns :: [Nat]) :: Constraint
- Numeric.Matrix: (%*) :: (ConcatList as bs (as ++ bs), Contraction t as bs asbs, KnownDim m, PrimArray t (DataFrame t (as +: m)), PrimArray t (DataFrame t (m :+ bs)), PrimArray t (DataFrame t (as ++ bs))) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t (as ++ bs)
+ Numeric.Matrix: (%*) :: (Contraction t as bs asbs, KnownDim m, PrimArray t (DataFrame t (as +: m)), PrimArray t (DataFrame t (m :+ bs)), PrimArray t (DataFrame t asbs)) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t asbs
- Numeric.Matrix: luSolve :: forall (t :: Type) (n :: Nat). (KnownDim n, Ord t, Fractional t, PrimBytes t, PrimArray t (Matrix t n n), PrimArray t (Vector t n)) => LUFact t n -> Vector t n -> Vector t n
+ Numeric.Matrix: luSolve :: forall (t :: Type) (n :: Nat). (KnownDim n, Fractional t, PrimArray t (Matrix t n n), PrimArray t (Vector t n)) => LUFact t n -> Vector t n -> Vector t n
- Numeric.Matrix: mat22 :: (PrimBytes (Vector (t :: Type) 2), PrimBytes (Matrix t 2 2)) => Vector t 2 -> Vector t 2 -> Matrix t 2 2
+ Numeric.Matrix: mat22 :: PrimBytes (t :: Type) => Vector t 2 -> Vector t 2 -> Matrix t 2 2
- Numeric.Matrix: mat33 :: (PrimBytes (t :: Type), PrimBytes (Vector t 3), PrimBytes (Matrix t 3 3)) => Vector t 3 -> Vector t 3 -> Vector t 3 -> Matrix t 3 3
+ Numeric.Matrix: mat33 :: PrimBytes (t :: Type) => Vector t 3 -> Vector t 3 -> Vector t 3 -> Matrix t 3 3
- Numeric.Matrix: mat44 :: forall (t :: Type). (PrimBytes t, PrimBytes (Vector t (4 :: Nat)), PrimBytes (Matrix t (4 :: Nat) (4 :: Nat))) => Vector t (4 :: Nat) -> Vector t (4 :: Nat) -> Vector t (4 :: Nat) -> Vector t (4 :: Nat) -> Matrix t (4 :: Nat) (4 :: Nat)
+ Numeric.Matrix: mat44 :: PrimBytes (t :: Type) => Vector t 4 -> Vector t 4 -> Vector t 4 -> Vector t 4 -> Matrix t 4 4
- Numeric.Matrix: pivotMat :: forall (t :: Type) (n :: k). (KnownDim n, PrimArray t (Matrix t n n), Ord t, Num t) => Matrix t n n -> (Matrix t n n, Matrix t n n, Scalar t)
+ Numeric.Matrix: pivotMat :: forall (t :: Type) (n :: Nat). (KnownDim n, PrimArray t (Matrix t n n), Ord t, Num t) => Matrix t n n -> (Matrix t n n, Matrix t n n, Scalar t)
- Numeric.PrimBytes: byteOffset :: (PrimBytes a, Generic a, GPrimBytes (Rep a)) => a -> Int#
+ Numeric.PrimBytes: byteOffset :: PrimBytes a => a -> Int#
- Numeric.PrimBytes: class PrimTagged a => PrimBytes a
+ Numeric.PrimBytes: class PrimTagged a => PrimBytes a where {
- Numeric.PrimBytes: getBytes :: (PrimBytes a, Generic a, GPrimBytes (Rep a)) => a -> ByteArray#
+ Numeric.PrimBytes: getBytes :: PrimBytes a => a -> ByteArray#
- Numeric.Quaternion: -- | Quaternion data type. The ordering of coordinates is <tt>x y z w</tt>,
+ Numeric.Quaternion: -- | Quaternion data type. The ordering of coordinates is
- Numeric.Scalar: fromScalar :: SubSpace t '[] ds ds => Scalar t -> DataFrame t ds
+ Numeric.Scalar: fromScalar :: SubSpace t ds '[] ds => Scalar t -> DataFrame t ds
- Numeric.Vector: (.*.) :: (Num t, Num (Vector t n), SubSpace t '[] '[n] '[n]) => Vector t n -> Vector t n -> Vector t n
+ Numeric.Vector: (.*.) :: (Num t, Num (Vector t n), SubSpace t '[n] '[] '[n]) => Vector t n -> Vector t n -> Vector t n
- Numeric.Vector: (·) :: (Num t, Num (Vector t n), SubSpace t '[] '[n] '[n]) => Vector t n -> Vector t n -> Scalar t
+ Numeric.Vector: (·) :: (Num t, Num (Vector t n), SubSpace t '[n] '[] '[n]) => Vector t n -> Vector t n -> Scalar t
- Numeric.Vector: (×) :: (Num t, SubSpace t '[] '[3] '[3]) => Vector t 3 -> Vector t 3 -> Vector t 3
+ Numeric.Vector: (×) :: (Num t, SubSpace t '[3] '[] '[3]) => Vector t 3 -> Vector t 3 -> Vector t 3
- Numeric.Vector: cross :: (Num t, SubSpace t '[] '[3] '[3]) => Vector t 3 -> Vector t 3 -> Vector t 3
+ Numeric.Vector: cross :: (Num t, SubSpace t '[3] '[] '[3]) => Vector t 3 -> Vector t 3 -> Vector t 3
- Numeric.Vector: det2 :: (Num t, SubSpace t '[] '[2] '[2]) => Vector t 2 -> Vector t 2 -> Scalar t
+ Numeric.Vector: det2 :: (Num t, SubSpace t '[2] '[] '[2]) => Vector t 2 -> Vector t 2 -> Scalar t
- Numeric.Vector: dot :: (Num t, Num (Vector t n), SubSpace t '[] '[n] '[n]) => Vector t n -> Vector t n -> Scalar t
+ Numeric.Vector: dot :: (Num t, Num (Vector t n), SubSpace t '[n] '[] '[n]) => Vector t n -> Vector t n -> Scalar t
- Numeric.Vector: normL1 :: (Num t, SubSpace t '[] '[n] '[n]) => Vector t n -> Scalar t
+ Numeric.Vector: normL1 :: (Num t, SubSpace t '[n] '[] '[n]) => Vector t n -> Scalar t
- Numeric.Vector: normL2 :: (Floating t, SubSpace t '[] '[n] '[n]) => Vector t n -> Scalar t
+ Numeric.Vector: normL2 :: (Floating t, SubSpace t '[n] '[] '[n]) => Vector t n -> Scalar t
- Numeric.Vector: normLNInf :: (Ord t, Num t, SubSpace t '[] '[n] '[n]) => Vector t n -> Scalar t
+ Numeric.Vector: normLNInf :: (Ord t, Num t, SubSpace t '[n] '[] '[n]) => Vector t n -> Scalar t
- Numeric.Vector: normLP :: (Floating t, SubSpace t '[] '[n] '[n]) => Int -> Vector t n -> Scalar t
+ Numeric.Vector: normLP :: (Floating t, SubSpace t '[n] '[] '[n]) => Int -> Vector t n -> Scalar t
- Numeric.Vector: normLPInf :: (Ord t, Num t, SubSpace t '[] '[n] '[n]) => Vector t n -> Scalar t
+ Numeric.Vector: normLPInf :: (Ord t, Num t, SubSpace t '[n] '[] '[n]) => Vector t n -> Scalar t
- Numeric.Vector: normalized :: (Floating t, Fractional (Vector t n), SubSpace t '[] '[n] '[n]) => Vector t n -> Vector t n
+ Numeric.Vector: normalized :: (Floating t, Fractional (Vector t n), SubSpace t '[n] '[] '[n]) => Vector t n -> Vector t n
- Numeric.Vector: vec2 :: SubSpace t '[] '[2] '[2] => t -> t -> Vector t 2
+ Numeric.Vector: vec2 :: Vector2 t => t -> t -> Vector t 2
- Numeric.Vector: vec3 :: SubSpace t '[] '[3] '[3] => t -> t -> t -> Vector t 3
+ Numeric.Vector: vec3 :: Vector3 t => t -> t -> t -> Vector t 3
- Numeric.Vector: vec4 :: SubSpace t '[] '[4] '[4] => t -> t -> t -> t -> Vector t 4
+ Numeric.Vector: vec4 :: Vector4 t => t -> t -> t -> t -> Vector t 4
Files
- bench/misc.hs +54/−51
- bench/subspacefolds.hs +19/−19
- easytensor.cabal +127/−124
- src-base/Numeric/DataFrame/Internal/Backend/Family.hs +183/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family.hs-boot +28/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/ArrayBase.hs +587/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/DoubleX2.hs +401/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/DoubleX3.hs +436/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/DoubleX4.hs +467/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/FloatX2.hs +401/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/FloatX3.hs +437/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/FloatX4.hs +498/−0
- src-base/Numeric/DataFrame/Internal/Backend/Family/ScalarBase.hs +50/−0
- src/Numeric/DataFrame.hs +7/−11
- src/Numeric/DataFrame/Contraction.hs +40/−19
- src/Numeric/DataFrame/Family.hs +0/−9
- src/Numeric/DataFrame/IO.hs +79/−43
- src/Numeric/DataFrame/Internal/Array.hs +0/−26
- src/Numeric/DataFrame/Internal/Array/Class.hs +0/−51
- src/Numeric/DataFrame/Internal/Array/Family.hs +0/−216
- src/Numeric/DataFrame/Internal/Array/Family/ArrayBase.hs +0/−498
- src/Numeric/DataFrame/Internal/Array/Family/DoubleX2.hs +0/−333
- src/Numeric/DataFrame/Internal/Array/Family/DoubleX3.hs +0/−362
- src/Numeric/DataFrame/Internal/Array/Family/DoubleX4.hs +0/−391
- src/Numeric/DataFrame/Internal/Array/Family/FloatX2.hs +0/−333
- src/Numeric/DataFrame/Internal/Array/Family/FloatX3.hs +0/−362
- src/Numeric/DataFrame/Internal/Array/Family/FloatX4.hs +0/−420
- src/Numeric/DataFrame/Internal/Array/Family/ScalarBase.hs +0/−51
- src/Numeric/DataFrame/Internal/Array/PrimOps.hs +0/−94
- src/Numeric/DataFrame/Internal/Backend.hs +221/−0
- src/Numeric/DataFrame/Internal/Backend.hs-boot +117/−0
- src/Numeric/DataFrame/Internal/BackendI.hs +197/−0
- src/Numeric/DataFrame/Internal/BackendI.hs-boot +9/−0
- src/Numeric/DataFrame/Internal/Mutable.hs +108/−51
- src/Numeric/DataFrame/Internal/PrimArray.hs +140/−0
- src/Numeric/DataFrame/ST.hs +66/−30
- src/Numeric/DataFrame/Shape.hs +0/−238
- src/Numeric/DataFrame/SubSpace.hs +342/−248
- src/Numeric/DataFrame/Type.hs +1140/−464
- src/Numeric/Matrix.hs +4/−326
- src/Numeric/Matrix/Class.hs +0/−151
- src/Numeric/Matrix/Internal.hs +473/−0
- src/Numeric/Matrix/Internal/Mat44d.hs +186/−0
- src/Numeric/Matrix/Internal/Mat44f.hs +186/−0
- src/Numeric/Matrix/Mat44d.hs +0/−196
- src/Numeric/Matrix/Mat44f.hs +0/−196
- src/Numeric/PrimBytes.hs +1792/−1428
- src/Numeric/ProductOrd.hs +128/−0
- src/Numeric/ProductOrd/NonTransitive.hs +315/−0
- src/Numeric/ProductOrd/Partial.hs +318/−0
- src/Numeric/Quaternion.hs +12/−14
- src/Numeric/Quaternion/Class.hs +0/−85
- src/Numeric/Quaternion/Internal.hs +154/−0
- src/Numeric/Quaternion/Internal/QDouble.hs +478/−0
- src/Numeric/Quaternion/Internal/QFloat.hs +478/−0
- src/Numeric/Quaternion/QDouble.hs +0/−559
- src/Numeric/Quaternion/QFloat.hs +0/−579
- src/Numeric/Scalar.hs +2/−35
- src/Numeric/Scalar/Internal.hs +43/−0
- src/Numeric/Semigroup.hs +0/−219
- src/Numeric/Vector.hs +6/−172
- src/Numeric/Vector/Internal.hs +229/−0
- test/Numeric/DataFrame/Arbitraries.hs +178/−62
- test/Numeric/DataFrame/BasicTest.hs +104/−31
- test/Numeric/DataFrame/SubSpaceTest.hs +19/−18
- test/Numeric/MatrixDoubleTest.hs +130/−114
- test/Numeric/MatrixFloatTest.hs +136/−114
- test/Numeric/PrimBytesTest.hs +411/−0
- test/Numeric/QuaterDoubleTest.hs +152/−0
- test/Numeric/QuaterFloatTest.hs +152/−0
- test/Numeric/QuaternionTest.hs +0/−124
- test/Spec.hs +19/−12
- test/Spec/Util.hs +154/−0
bench/misc.hs view
@@ -5,70 +5,73 @@ module Main (main) where -import Numeric.DataFrame-import Numeric.Dimensions+import Numeric.DataFrame+import Numeric.Dimensions -import qualified Control.Monad.ST as ST+import qualified Control.Monad.ST as ST import qualified Numeric.DataFrame.ST as ST--- import qualified Numeric.Dimensions.Traverse.ST as ST main :: IO () main = do putStrLn "Hello world!"- print (D @3 :* D @2 :* U)+ print (D3 :* D2 :* U) - print (fromList D [vec2 1 0, vec2 2 3, vec2 3 4, vec2 5 6]- :: Maybe (DataFrame Int '[N 2, XN 2]))- print (fromList D [vec4 1 0 2 11, vec4 2 22 3 0, vec4 3 4 0 0]- :: Maybe (DataFrame Double '[N 4, XN 0]))- print (fromList D [vec2 0 0, vec2 2 22, vec2 2 22]- :: Maybe (DataFrame Float '[N 2, XN 4]))- print $ fromList (D @3) [0 :: Scf, 1, 3, 5, 7]- print ( fromList D [9, 13, 2]- :: Maybe (DataFrame Float '[N 5, N 2, XN 2]))+ print (fromList [vec2 1 0, vec2 2 3, vec2 3 4, vec2 5 6]+ :: DataFrame Int '[XN 0, N 2])+ print (fromList [vec4 1 0 2 11, vec4 2 22 3 0, vec4 3 4 0 0]+ :: DataFrame Double '[XN 0, N 4])+ print (fromList [vec2 0 0, vec2 2 22, vec2 2 22]+ :: DataFrame Float '[XN 0, N 2])+ print $ fromList [0 :: Scf, 1, 3, 5, 7]+ print ( fromList [9, 13, 2]+ :: DataFrame Float '[XN 0, N 5, N 2]) print $ vec2 1 1 %* mat22 1 (vec2 2 (3 :: Float))- print (toList (42 :: DataFrame Int '[4,3,2]))+ -- Seems like I have to specify known dimension explicitly, -- because the inference process within the pattern match -- cannot escape the case expression. -- On the other hand, if I type wrong dimension it will throw a nice type-level error.- () <- case fromList D [10, 100, 1000] :: Maybe (DataFrame Double '[N 4, N 2, XN 2]) of- Just (XFrame m)+ () <- case (fromList [10, 100, 1000] :: DataFrame Double '[XN 0, N 2, N 4]) of+ XFrame m | KnownDims <- dims `inSpaceOf` m -- Amazing inference!- -- m :: KnownNat k => DataFrame '[4,2,k]- -> print $ vec4 1 2.25 3 0.162 %* m- Nothing -> print "Failed to construct a DataFrame!"+ -- m :: KnownNat k => DataFrame '[k,2,4]+ -> print $ m %* vec4 1 2.25 3 0.162+ _ -> print "Failed to construct a DataFrame!" putStrLn "Constructing larger matrices"- let x :: DataFrame Double '[2,5,4]- x = transpose ( (56707.4 <::> 73558.41 <+:> 47950.074 <+:> 83394.61 <+:> 25611.629 )- <::> (53704.516 <::> -3277.478 <+:> 99479.92 <+:> 18915.17 <+:> 59666.938 ) )- <::> transpose ( (-3035.543 <::> 15831.447 <+:> 73256.625 <+:> 80709.38 <+:> 72695.04 )- <::> (50932.49 <::> 7865.496 <+:> -4050.5957 <+:> 99839.41 <+:> 10834.297 ) )- <+:> transpose ( (21961.227 <::> 29640.914 <+:> 39657.19 <+:> 81469.64 <+:> 17815.506 )- <::> (-8484.239 <::> 16877.531 <+:> 65145.742 <+:> 80219.67 <+:> 81508.87 ) )- <+:> transpose ( (53105.71 <::> 16255.646 <+:> 23324.957 <+:> -4438.164 <+:> 35369.824 )- <::> (67930.45 <::> 8950.834 <+:> 64451.71 <+:> 76685.57 <+:> 6728.465 ) )- y :: DataFrame Double '[3,7]- y = transpose $- (70096.85 <::> 34332.492 <+:> 3642.8867 <+:> 25242.25 <+:> 59776.234 <+:> 12092.57 <+:> 10708.498)- <::> (46447.965 <::> 37145.668 <+:> 56899.656 <+:> 85367.56 <+:> 15872.262 <+:> 87466.24 <+:> 82506.76 )- <+:> (50458.848 <::> 31650.453 <+:> 71432.78 <+:> 53073.203 <+:> 59267.883 <+:> 82369.89 <+:> 78171.56 )- z = ewgen x :: DataFrame Double '[2,5,4,3,7]- print $ ewfoldl @_ @'[2] (+) 10 z- print $ ewfoldr @_ @'[2,5] (+) 0 z + 10- print $ ewfoldl (+) 10 z - ewfoldr @_ @'[2,5,4] (+) 0 z - 10+ let x :: DataFrame Double '[4,5,2]+ x = DF4 (transpose $ DF2+ (DF5 56707.4 73558.41 47950.074 83394.61 25611.629)+ (DF5 53704.516 (-3277.478) 99479.92 18915.17 59666.938))+ (transpose $ DF2+ (DF5 (-3035.543) 15831.447 73256.625 80709.38 72695.04)+ (DF5 50932.49 7865.496 (-4050.5957) 99839.41 10834.297))+ (transpose $ DF2+ (DF5 21961.227 29640.914 39657.19 81469.64 17815.506 )+ (DF5 (-8484.239) 16877.531 65145.742 80219.67 81508.87 ))+ (transpose $ DF2+ (DF5 53105.71 16255.646 23324.957 (-4438.164) 35369.824 )+ (DF5 67930.45 8950.834 64451.71 76685.57 6728.465 ))+ y :: DataFrame Double '[7,3]+ y = transpose $ DF3+ (DF7 70096.85 34332.492 3642.8867 25242.25 59776.234 12092.57 10708.498)+ (DF7 46447.965 37145.668 56899.656 85367.56 15872.262 87466.24 82506.76 )+ (DF7 50458.848 31650.453 71432.78 53073.203 59267.883 82369.89 78171.56 )+ z = ewgen x :: DataFrame Double '[7,3,4,5,2]+ print $ ewfoldl @_ @_ @'[2] (+) 10 z+ print $ ewfoldr @_ @_ @'[5,2] (+) 0 z + 10+ print $ ewfoldl (+) 10 z - ewfoldr @_ @_ @'[4,5,2] (+) 0 z - 10 - -- We can map arbitrary prefix dimension over the dataframe,- -- indexing by suffix dimensions.+ -- We can map arbitrary suffix dimension over the dataframe,+ -- indexing by prefix dimensions. -- At the same time, we can transform underlying element type- -- or prefix dimensionality.+ -- or suffix dimensionality. -- For example, we can do tensor produt of every sub-tensor. putStrLn "\nConversions between element types and frame sizes."- print $ iwmap @Int @'[2,2] @'[7] @_- (\(Idx i:*U) v -> fromScalar . (scalar (fromIntegral i) +) . round+ print $ iwmap @Int @'[7] @'[2,2] @_+ (\(i:*U) v -> fromScalar . (scalar (fromIntegral i) +) . round $ vec3 0.02 (-0.01) 0.001 %* v ) y @@ -77,27 +80,27 @@ -- This means we can even do arbitrary IO for each subtensor -- indexed by suffix dimensions. putStrLn "\nWelement-wise IO!"- rVec <- elementWise @Double @_ @'[4] @_+ rVec <- elementWise @Double @'[4] @_ @_ (\v -> print v >> return (sqrt . trace $ v %* transpose v)) x putStrLn "\nTraces for each matrix element:" print rVec -- Updating existing frames print $ update (2:*U) (scalar 777) rVec- print $ update (2:*3:*U) (vec2 999 999) x+ print $ update (1:*3:*U) (vec2 999 555) x - let matX = iwgen (scalar . fromEnum) :: DataFrame Int '[2,5,4]+ let matX = iwgen (scalar . fromEnum) :: DataFrame Int '[2,6,4] matY = iwgen (scalar . fromEnum) :: DataFrame Int '[5,4] putStrLn "Check carefully that this returns no garbage" print matX- print (ewmap (<+:> scalar 111) matX :: DataFrame Int '[3,5,4])+ print (ewmap @_ @'[2,6] (`snocDF` scalar 111) matX :: DataFrame Int '[2,6,5]) print matY- print (ewmap fromScalar matY :: DataFrame Int '[3,5,4])+ print (ewmap fromScalar matY :: DataFrame Int '[5,4,3]) -- Working with mutable frames print $ ST.runST $ do sdf <- ST.thawDataFrame matY- ST.writeDataFrame sdf (1:*1:*U) 900101- ST.writeDataFrame sdf (3:*3:*U) 900303- ST.writeDataFrame sdf (5:*3:*U) 900503+ ST.writeDataFrame sdf (0:*0:*U) 900101+ ST.writeDataFrame sdf (2:*2:*U) 900303+ ST.writeDataFrame sdf (4:*2:*U) 900503 ST.unsafeFreezeDataFrame sdf
bench/subspacefolds.hs view
@@ -5,58 +5,58 @@ module Main (main) where -import Data.Maybe (fromMaybe)-import Data.Time.Clock+import Data.Maybe (fromMaybe)+import Data.Time.Clock -import Numeric.DataFrame-import Numeric.Dimensions+import Numeric.DataFrame+import Numeric.Dimensions -type DList = [6,4,10,7,35,8,12] -- [6,26,8,10,35,8,12]+type DList = [6,14,10,7,2,8,5] main :: IO () main = do t0 <- getCurrentTime putStrLn $ "\nStarting benchmarks, current time is " ++ show t0- let df = iwgen @Float @'[] @DList (fromIntegral . fromEnum)+ let df = iwgen @Float @DList @'[] (fromIntegral . fromEnum) t1 <- df `seq` getCurrentTime seq t1 putStrLn $ "Created DataFrame, elapsed time is " ++ show (diffUTCTime t1 t0) putStrLn "\nRunning a ewfoldl on scalar elements..."- let rezEwf = ewfoldl @Float @'[] @DList (\a x -> return $! fromMaybe x a + fromMaybe 0 a / (x+1)) (Just 1) df+ let rezEwf = ewfoldl @Float @DList @'[] (\a x -> return $! fromMaybe x a + fromMaybe 0 a / (x+1)) (Just 1) df t2 <- rezEwf `seq` getCurrentTime seq t2 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t2 t1) print rezEwf putStrLn "\nRunning a iwfoldl on scalar elements (not using idx)..."- let rezIwf = iwfoldl @Float @'[] @DList (\_ a x -> a + a / (x+1)) 1 df+ let rezIwf = iwfoldl @Float @DList @'[] (\_ a x -> a + a / (x+1)) 1 df t3 <- rezIwf `seq` getCurrentTime seq t3 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t3 t2) print rezIwf putStrLn "\nRunning a iwfoldr on scalar elements (using fromEnum idx)..."- let rezIwf2 = iwfoldr @Float @'[] @DList (\i x a -> return $! fromMaybe 0 a + x / ((1+) . fromIntegral $ fromEnum i)) (Just 0) df+ let rezIwf2 = iwfoldr @Float @DList @'[] (\i x a -> return $! fromMaybe 0 a + x / ((1+) . fromIntegral $ fromEnum i)) (Just 0) df t4 <- rezIwf2 `seq` getCurrentTime seq t4 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t4 t3) print rezIwf2 putStrLn "\nRunning a iwfoldl on scalar elements (enforcing idx)..."- let rezIwf3 = iwfoldl @Float @'[] @DList (\i a x -> i `seq` return $! fromMaybe 0 a + fromMaybe x a / (x+1)) (Just 1) df+ let rezIwf3 = iwfoldl @Float @DList @'[] (\i a x -> i `seq` return $! fromMaybe 0 a + fromMaybe x a / (x+1)) (Just 1) df t5 <- rezIwf3 `seq` getCurrentTime seq t5 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t5 t4) print rezIwf3 - putStrLn "\nRunning a ewfoldl on vector5 elements..."- let rezEwv1 = ewfoldl @Float @'[Head DList] @(Tail DList)- (\a x -> return $! fromMaybe 2 a + fromMaybe 0 a / (1 + iwgen @_ @'[] (\(Idx i:*U) -> Idx (i+1) :* U !. x )) )- (Just (3 :: DataFrame Float '[5])) df+ putStrLn "\nRunning a ewfoldl on vector4 elements..."+ let rezEwv1 = ewfoldl @Float @(Init DList) @'[Last DList]+ (\a x -> return $! fromMaybe 2 a + fromMaybe 0 a / (1 + iwgen @_ @_ @'[] (\(Idx i:*U) -> x ! Idx (i+1) :* U )) )+ (Just (3 :: DataFrame Float '[4])) df t6 <- rezEwv1 `seq` getCurrentTime seq t6 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t6 t5) print rezEwv1 putStrLn "\nRunning a ewfoldr on vector3 elements..."- let rezEwv2 = ewfoldr @Float @'[Head DList] @(Tail DList)- (\x a -> return $! fromMaybe 2 a + fromMaybe 1 a / (1 + iwgen @_ @'[] (\(Idx i:*U) -> Idx (i+1):* U !. x )))+ let rezEwv2 = ewfoldr @Float @(Init DList) @'[Last DList]+ (\x a -> return $! fromMaybe 2 a + fromMaybe 1 a / (1 + iwgen @_ @_ @'[] (\(Idx i:*U) -> x ! Idx (i+1):* U ))) (Just (3 :: DataFrame Float '[3])) df t7 <- rezEwv2 `seq` getCurrentTime seq t7 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t7 t6)@@ -64,8 +64,8 @@ putStrLn "\nRunning a ewfoldr with matrix products..." let rezEwm = ewfoldr @Float @(Take 3 DList) @(Drop 3 DList)- (\x a -> a + x %* (1 <::> 0.5 <:> 0.1) )- (1 :: DataFrame Float (Take 2 DList +: 3)) df+ (\x a -> a + x %* (DF5 1 0.5 0.1 0.01 0.001) )+ (1 :: DataFrame Float (Init (Drop 3 DList) +: 3)) df t8 <- rezEwm `seq` getCurrentTime seq t8 putStrLn $ "Done; elapsed time = " ++ show (diffUTCTime t8 t7) print rezEwm@@ -74,4 +74,4 @@ putStrLn "Checking indexes"- print $ 2:*1:*1:*3:*1:*U !. df+ print $ df ! (2:*1:*1:*3:*1:*U :: Idxs (Take 5 DList))
easytensor.cabal view
@@ -1,136 +1,139 @@-name: easytensor-version: 1.0.1.0-cabal-version: >=1.22-build-type: Simple-license: BSD3-license-file: LICENSE-copyright: (c) Artem Chirkin-maintainer: chirkin@arch.ethz.ch-homepage: https://github.com/achirkin/easytensor#readme-synopsis: Pure, type-indexed haskell vector, matrix, and tensor library.-description:- Pure, type-indexed haskell vector, matrix, and tensor library.- Features dimensionality type-checking for all operations.- Generic n-dimensional versions are implemented using low-level prim ops.- Allows ad-hoc replacement with fixed low-dimensionality vectors and matrices without changing user interface.-category: Math, Geometry-author: Artem Chirkin+cabal-version: 1.12 -source-repository head- type: git- location: https://github.com/achirkin/easytensor.git- subdir: easytensor+-- This file has been generated from package.yaml by hpack version 0.31.1.+--+-- see: https://github.com/sol/hpack+--+-- hash: 295fd017e3f09157b9e9a28d1db9beb6ecb080f0612228ac49f18e78ee08d01b +name: easytensor+version: 2.0.0.0+synopsis: Pure, type-indexed haskell vector, matrix, and tensor library.+description: Pure, type-indexed haskell vector, matrix, and tensor library. Features dimensionality type-checking for all operations. Generic n-dimensional versions are implemented using low-level prim ops. Allows ad-hoc replacement with fixed low-dimensionality vectors and matrices without changing user interface. Please see the README on GitHub at <https://github.com/achirkin/easytensor#readme>+category: math, geometry+homepage: https://github.com/achirkin/easytensor#readme+bug-reports: https://github.com/achirkin/easytensor/issues+author: Artem Chirkin+maintainer: achirkin@users.noreply.github.com+copyright: Copyright: (c) 2019 Artem Chirkin+license: BSD3+license-file: LICENSE+build-type: Simple -flag unsafeindices- description:- Disable bound checks when accessing elements of a tensor, matrix, or vector.- default: False+source-repository head+ type: git+ location: https://github.com/achirkin/easytensor+ subdir: easytensor +flag unsafeindices+ description: Disable bound checks when accessing elements of a tensor, matrix, or vector.+ manual: True+ default: False library-- if flag(unsafeindices)- cpp-options: -DUNSAFE_INDICES- exposed-modules:- Numeric.DataFrame- Numeric.DataFrame.IO- Numeric.DataFrame.ST- Numeric.Matrix- Numeric.Matrix.Class- Numeric.Vector- Numeric.Scalar- Numeric.Quaternion- Numeric.Semigroup- Numeric.PrimBytes- Numeric.DataFrame.Type- Numeric.DataFrame.Family- Numeric.DataFrame.Shape- Numeric.DataFrame.SubSpace- Numeric.DataFrame.Contraction- Numeric.DataFrame.Internal.Mutable- Numeric.DataFrame.Internal.Array- Numeric.DataFrame.Internal.Array.Class- Numeric.DataFrame.Internal.Array.Family- Numeric.DataFrame.Internal.Array.Family.ArrayBase- Numeric.DataFrame.Internal.Array.Family.ScalarBase- Numeric.DataFrame.Internal.Array.Family.FloatX2- Numeric.DataFrame.Internal.Array.Family.FloatX3- Numeric.DataFrame.Internal.Array.Family.FloatX4- Numeric.DataFrame.Internal.Array.Family.DoubleX2- Numeric.DataFrame.Internal.Array.Family.DoubleX3- Numeric.DataFrame.Internal.Array.Family.DoubleX4- Numeric.DataFrame.Internal.Array.PrimOps- build-depends:- base >=4.10 && <5,- dimensions >=1.0.0.0- default-language: Haskell2010- if impl(ghc >= 8.6)- default-extensions: NoStarIsType- hs-source-dirs: src- other-modules:- Numeric.Matrix.Mat44d- Numeric.Matrix.Mat44f- Numeric.Quaternion.Class- Numeric.Quaternion.QDouble- Numeric.Quaternion.QFloat- ghc-options:- -Wall- -fwarn-tabs- -fwarn-unused-do-bind- -fwarn-monomorphism-restriction-+ exposed-modules:+ Numeric.DataFrame+ Numeric.DataFrame.Contraction+ Numeric.DataFrame.Internal.Backend+ Numeric.DataFrame.Internal.Mutable+ Numeric.DataFrame.Internal.PrimArray+ Numeric.DataFrame.IO+ Numeric.DataFrame.ST+ Numeric.DataFrame.SubSpace+ Numeric.DataFrame.Type+ Numeric.Matrix+ Numeric.PrimBytes+ Numeric.ProductOrd+ Numeric.ProductOrd.NonTransitive+ Numeric.ProductOrd.Partial+ Numeric.Quaternion+ Numeric.Scalar+ Numeric.Vector+ other-modules:+ Numeric.Matrix.Internal+ Numeric.Matrix.Internal.Mat44d+ Numeric.Matrix.Internal.Mat44f+ Numeric.Scalar.Internal+ Numeric.Vector.Internal+ Numeric.Quaternion.Internal+ Numeric.Quaternion.Internal.QDouble+ Numeric.Quaternion.Internal.QFloat+ Numeric.DataFrame.Internal.Backend.Family+ Numeric.DataFrame.Internal.Backend.Family.ArrayBase+ Numeric.DataFrame.Internal.Backend.Family.DoubleX2+ Numeric.DataFrame.Internal.Backend.Family.DoubleX3+ Numeric.DataFrame.Internal.Backend.Family.DoubleX4+ Numeric.DataFrame.Internal.Backend.Family.FloatX2+ Numeric.DataFrame.Internal.Backend.Family.FloatX3+ Numeric.DataFrame.Internal.Backend.Family.FloatX4+ Numeric.DataFrame.Internal.Backend.Family.ScalarBase+ Numeric.DataFrame.Internal.BackendI+ hs-source-dirs:+ src+ src-base+ ghc-options: -Wall -Wcompat -Wtabs -Wmonomorphism-restriction -Wmissing-local-signatures -Wmissing-home-modules -Widentities -Wredundant-constraints+ build-depends:+ base >=4.11 && <5+ , constraints-deriving >=1.0.4.0 && <2+ , dimensions >=2 && <3+ if flag(unsafeindices)+ cpp-options: -DUNSAFE_INDICES+ default-language: Haskell2010 test-suite et-test-- type: exitcode-stdio-1.0- main-is: Spec.hs- other-modules:- Numeric.DataFrame.Arbitraries- Numeric.DataFrame.SubSpaceTest- Numeric.DataFrame.BasicTest- Numeric.MatrixDoubleTest- Numeric.MatrixFloatTest- Numeric.QuaternionTest- build-depends:- base -any,- Cabal -any,- QuickCheck -any,- easytensor -any,- dimensions -any- default-language: Haskell2010- if impl(ghc >= 8.6)- default-extensions: NoStarIsType, NoMonadFailDesugaring- hs-source-dirs: test- ghc-options: -Wall -fwarn-tabs -O2-+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Numeric.DataFrame.Arbitraries+ Numeric.DataFrame.BasicTest+ Numeric.DataFrame.SubSpaceTest+ Numeric.MatrixDoubleTest+ Numeric.MatrixFloatTest+ Numeric.PrimBytesTest+ Numeric.QuaterDoubleTest+ Numeric.QuaterFloatTest+ Spec.Util+ Paths_easytensor+ hs-source-dirs:+ test+ ghc-options: -Wall -Wcompat -Wtabs -Wmonomorphism-restriction -Wmissing-local-signatures -Wmissing-home-modules -Widentities -Wredundant-constraints+ build-depends:+ Cabal+ , QuickCheck+ , base >=4.11 && <5+ , constraints-deriving >=1.0.4.0 && <2+ , dimensions >=2 && <3+ , easytensor+ , template-haskell+ default-language: Haskell2010 benchmark et-bench-misc-- type: exitcode-stdio-1.0- main-is: misc.hs- build-depends:- base -any,- easytensor -any,- dimensions -any- default-language: Haskell2010- if impl(ghc >= 8.6)- default-extensions: NoStarIsType, NoMonadFailDesugaring- hs-source-dirs: bench- ghc-options: -Wall -fwarn-tabs -O2-+ type: exitcode-stdio-1.0+ main-is: misc.hs+ other-modules:+ Paths_easytensor+ hs-source-dirs:+ bench+ ghc-options: -Wall -Wcompat -Wtabs -Wmonomorphism-restriction -Wmissing-local-signatures -Wmissing-home-modules -Widentities -Wredundant-constraints+ build-depends:+ base >=4.11 && <5+ , constraints-deriving >=1.0.4.0 && <2+ , dimensions >=2 && <3+ , easytensor+ default-language: Haskell2010 benchmark et-bench-spfolds-- type: exitcode-stdio-1.0- main-is: subspacefolds.hs- build-depends:- base -any,- easytensor -any,- dimensions -any,- time -any- default-language: Haskell2010- if impl(ghc >= 8.6)- default-extensions: NoStarIsType, NoMonadFailDesugaring- hs-source-dirs: bench- ghc-options: -Wall -fwarn-tabs -O2+ type: exitcode-stdio-1.0+ main-is: subspacefolds.hs+ other-modules:+ Paths_easytensor+ hs-source-dirs:+ bench+ ghc-options: -Wall -Wcompat -Wtabs -Wmonomorphism-restriction -Wmissing-local-signatures -Wmissing-home-modules -Widentities -Wredundant-constraints+ build-depends:+ base >=4.11 && <5+ , constraints-deriving >=1.0.4.0 && <2+ , dimensions >=2 && <3+ , easytensor+ , time+ default-language: Haskell2010
+ src-base/Numeric/DataFrame/Internal/Backend/Family.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE TypeOperators #-}+-- Constraints @b ~ BackendFamily t ds@ is not redundant; they allows to avoid AllowAmbigousTypes.+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+{- |+This module is to be reimplemented multiple times based on a platform capabilities.+For example, I can add a SIMD implementation in a separate folder and use AVX+processsor extensions to make faster 4D vector operations.++Various implementations would be picked by activating corresponding cabal flags.++The following export list must be the same for every implementation+ -}+module Numeric.DataFrame.Internal.Backend.Family+ ( BackendFamily, KnownBackend ()+ , inferKnownBackend, inferPrimElem, inferPrimArray, inferBackendInstance+ ) where+++import Data.Constraint+import GHC.Base++import Numeric.DataFrame.Internal.Backend.Family.ArrayBase+import Numeric.DataFrame.Internal.Backend.Family.DoubleX2+import Numeric.DataFrame.Internal.Backend.Family.DoubleX3+import Numeric.DataFrame.Internal.Backend.Family.DoubleX4+import Numeric.DataFrame.Internal.Backend.Family.FloatX2+import Numeric.DataFrame.Internal.Backend.Family.FloatX3+import Numeric.DataFrame.Internal.Backend.Family.FloatX4+import Numeric.DataFrame.Internal.Backend.Family.ScalarBase+import Numeric.DataFrame.Internal.PrimArray+import Numeric.Dimensions+import Numeric.PrimBytes+++-- | This type family aggregates all types used for arrays with different+-- dimensioinality.+-- The family is injective; thus, it is possible to get type family instance+-- given the data constructor (and vice versa).+-- If GHC knows the dimensionality of a backend at compile time, it chooses+-- a more efficient specialized instance of @BackendFamily@, e.g. Scalar newtype wrapper.+-- Otherwise, it falls back to the generic ArrayBase implementation.+--+-- Data family would not work here, because it would give overlapping instances.+type family BackendFamily (t :: Type) (ds :: [Nat]) = (v :: Type) | v -> t ds where+ BackendFamily t '[] = ScalarBase t+ BackendFamily Float '[2] = FloatX2+ BackendFamily Float '[3] = FloatX3+ BackendFamily Float '[4] = FloatX4+ BackendFamily Double '[2] = DoubleX2+ BackendFamily Double '[3] = DoubleX3+ BackendFamily Double '[4] = DoubleX4+ BackendFamily t ds = ArrayBase t ds++-- | Promise that we are sure the backend is ArrayBase.+unsafeDefault :: forall t ds . Dict (BackendFamily t ds ~ ArrayBase t ds)+unsafeDefault = unsafeCoerce# (Dict @(ArrayBase t ds ~ ArrayBase t ds))++-- | Singleton type used to determine the currently used DataFrame backend;+-- establishes a good bijection @b <~> t ds@ (better than just using @BackendFamily@ everywhere).+data BackendSing (t :: Type) (ds :: [Nat]) (backend :: Type) where+ BSC :: BackendSing t '[] (ScalarBase t)+ BF2 :: BackendSing Float '[2] FloatX2+ BF3 :: BackendSing Float '[3] FloatX3+ BF4 :: BackendSing Float '[4] FloatX4+ BD2 :: BackendSing Double '[2] DoubleX2+ BD3 :: BackendSing Double '[3] DoubleX3+ BD4 :: BackendSing Double '[4] DoubleX4+ BPB :: ( PrimBytes t, BackendFamily t ds ~ ArrayBase t ds )+ => BackendSing t ds (ArrayBase t ds)++-- | A framework for using DataFrame type family instances.+class KnownBackend (t :: Type) (ds :: [Nat]) (backend :: Type) where+ -- | Get DataFrame backend type family instance+ bSing :: BackendSing t ds backend++-- When compiled for haddock, some of the modules complain about missing KnownBackend+-- instance. To workaround this, I add an instance stub.+--+-- Also note, these may be related issues:+--+-- https://github.com/haskell/haddock/issues/680+-- https://github.com/haskell/cabal/issues/4513+--+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)+instance KnownBackend t ds b where bSing = undefined+#else+instance KnownBackend t '[] (ScalarBase t) where bSing = BSC+instance KnownBackend Float '[2] FloatX2 where bSing = BF2+instance KnownBackend Float '[3] FloatX3 where bSing = BF3+instance KnownBackend Float '[4] FloatX4 where bSing = BF4+instance KnownBackend Double '[2] DoubleX2 where bSing = BD2+instance KnownBackend Double '[3] DoubleX3 where bSing = BD3+instance KnownBackend Double '[4] DoubleX4 where bSing = BD4+instance PrimBytes t+ => KnownBackend t ds (ArrayBase t ds) where+ bSing = case unsafeDefault @t @ds of Dict -> BPB+#endif++-- | Find an instance of `KnownBackend` class using `PrimBytes` and `Dimensions`.+inferKnownBackend :: forall t ds b+ . (PrimBytes t, Dimensions ds, b ~ BackendFamily t ds)+ => Dict (KnownBackend t ds b)+inferKnownBackend = case (dims @ds, primTag @t undefined) of+ (U, _) -> Dict+ (d :* U, PTagFloat)+ | Just Dict <- sameDim (D @2) d -> Dict+ | Just Dict <- sameDim (D @3) d -> Dict+ | Just Dict <- sameDim (D @4) d -> Dict+ (d :* U, PTagDouble)+ | Just Dict <- sameDim (D @2) d -> Dict+ | Just Dict <- sameDim (D @3) d -> Dict+ | Just Dict <- sameDim (D @4) d -> Dict+ _ -> case unsafeDefault @t @ds of Dict -> Dict+{-# INLINE inferKnownBackend #-}+++-- This function determines the logic of instance selection+-- for the type family+inferBackendInstance+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (c :: Type -> Constraint)+ . ( KnownBackend t ds b+ , c (ScalarBase t)+ , c FloatX2, c FloatX3, c FloatX4+ , c DoubleX2, c DoubleX3, c DoubleX4+ , c (ArrayBase t ds)+ , b ~ BackendFamily t ds+ )+ => Dict (c b)+inferBackendInstance = case bSing @t @ds @b of+ BSC -> Dict+ BF2 -> Dict+ BF3 -> Dict+ BF4 -> Dict+ BD2 -> Dict+ BD3 -> Dict+ BD4 -> Dict+ BPB -> Dict+{-# INLINE inferBackendInstance #-}++inferPrimElem :: forall (t :: Type) (d :: Nat) (ds :: [Nat]) (b :: Type)+ . ( KnownBackend t (d ': ds) b+ , b ~ BackendFamily t (d ': ds)+ )+ => b -> Dict (PrimBytes t)+inferPrimElem _ = case bSing @t @(d ': ds) @b of+ BF2 -> Dict+ BF3 -> Dict+ BF4 -> Dict+ BD2 -> Dict+ BD3 -> Dict+ BD4 -> Dict+ BPB -> Dict++-- Need a separate function for this one due to a functional dependency+inferPrimArray+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, KnownBackend t ds b, b ~ BackendFamily t ds)+ => Dict (PrimArray t b)+inferPrimArray = case bSing @t @ds @b of+ BSC -> Dict+ BF2 -> Dict+ BF3 -> Dict+ BF4 -> Dict+ BD2 -> Dict+ BD3 -> Dict+ BD4 -> Dict+ BPB -> Dict+{-# INLINE inferPrimArray #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family.hs-boot view
@@ -0,0 +1,28 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilyDependencies #-}++module Numeric.DataFrame.Internal.Backend.Family+ ( BackendFamily, KnownBackend ()+ ) where++import Data.Kind (Type)+import GHC.TypeLits (Nat)+++type family BackendFamily (t :: Type) (ds :: [Nat]) = (v :: Type) | v -> t ds where ..+class KnownBackend (t :: Type) (ds :: [Nat]) (backend :: Type)++-- When compiled for haddock, some of the modules complain about missing KnownBackend+-- instance. To workaround this, I add an instance stub.+--+-- Also note, these may be related issues:+--+-- https://github.com/haskell/haddock/issues/680+-- https://github.com/haskell/cabal/issues/4513+--+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)+instance KnownBackend t ds b+#endif
+ src-base/Numeric/DataFrame/Internal/Backend/Family/ArrayBase.hs view
@@ -0,0 +1,587 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}++module Numeric.DataFrame.Internal.Backend.Family.ArrayBase+ ( ArrayBase (..)+ ) where++import Data.Coerce+import Data.Int+import Data.Word+import GHC.Base hiding (foldr)+import Numeric.DataFrame.Internal.PrimArray+import Numeric.Dimensions+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial++-- | Generic Array implementation.+-- This array can reside in plain `ByteArray#` and can share the @ByteArray#@+-- with other arrays.+-- However, byte offset in the @ByteArray#@ must be multiple of the element size.+data ArrayBase (t :: Type) (ds :: [Nat])+ = ArrayBase+ (# t -- Same value for each element;+ -- this is the cheapest way to initialize an array.+ -- It is also used for Num instances to avoid dependency on Dimensions.+ | (# Int# -- Offset in Content array (measured in elements)+ , ByteArray# -- Content;+ -- elements are stored row-by-row, plane-by-plane;+ -- (C-style, rather than Fortran-style);+ -- similar to C, OpenCV, etc.+ -- The data must be contiguous!+ -- (i.e. stride must be the same size as the element size).+ , CumulDims -- Steps array; [Word]+ -- similar to steps in OpenCV::Mat, but counted in elements+ -- rather than in bytes.+ -- e.g. 0th element is the size of the content in elements+ -- (data must be contiguous)+ -- 1th element is the size of subspace data minus outer dim.+ , Dict (PrimBytes t)+ #)+ #)+++instance (PrimBytes t, Dimensions ds) => PrimBytes (ArrayBase t ds) where+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Double ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word64 ds) #-}++ getBytes (ArrayBase a ) = case a of+ (# t | #)+ | W# nw <- totalDim' @ds+ , n <- word2Int# nw+ , tbs <- byteSize t -> go tbs (tbs *# n) t+ (# | (# _, arr, _, _ #) #) ->+ -- very weird trick with touch# allows to workaround GHC bug+ -- "internal error: ARR_WORDS object entered!"+ -- TODO: report this+ case runRW# (\s -> (# touch# arr s, arr #)) of (# _, ba #) -> ba+ where+ go :: Int# -> Int# -> t -> ByteArray#+ go tbs bsize t = case runRW#+ ( \s0 -> case newByteArray# bsize s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( loop# 0# tbs bsize (\i -> writeBytes mba i t) s1 )+ ) of (# _, ba #) -> ba+ {-# NOINLINE go #-}+ {-# INLINE getBytes #-}++ getBytesPinned (ArrayBase a) = case a of+ (# t | #)+ | W# nw <- totalDim' @ds+ , n <- word2Int# nw+ , tbs <- byteSize t -> go tbs (tbs *# n) t+ (# | (# off, arr, steps, _ #) #) ->+ if isTrue# (isByteArrayPinned# arr)+ then case runRW# (\s -> (# touch# arr s, arr #)) of (# _, ba #) -> ba+ else case runRW#+ ( \s0 -> case (# cdTotalDim# steps+ , byteSize @t undefined+ , byteAlign @t undefined+ #) of+ (# n, tbs, tba #)+ | bsize <- tbs *# n+ , (# s1, mba #) <- newAlignedPinnedByteArray# bsize tba s0+ , s2 <- copyByteArray# arr off mba 0# bsize s1+ -> unsafeFreezeByteArray# mba s2+ ) of (# _, ba #) -> ba+ where+ go :: Int# -> Int# -> t -> ByteArray#+ go tbs bsize t = case runRW#+ ( \s0 -> case newAlignedPinnedByteArray# bsize (byteAlign t) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( loop# 0# tbs bsize (\i -> writeBytes mba i t) s1 )+ ) of (# _, ba #) -> ba+ {-# NOINLINE go #-}+ {-# INLINE getBytesPinned #-}+++ fromBytes bOff ba+ | tbs <- byteSize (undefined :: t)+ , (# offN, offRem #) <- quotRemInt# bOff tbs+ = case offRem of+ 0# -> ArrayBase (# | (# offN, ba, steps, Dict #) #)+ _ -> case cdTotalDim# steps of n -> go (tbs *# n)+ where+ steps = cumulDims $ dims @ds+ go bsize = case runRW#+ ( \s0 -> case ( if isTrue# (isByteArrayPinned# ba)+ then newAlignedPinnedByteArray# bsize+ (byteAlign @t undefined)+ else newByteArray# bsize+ ) s0+ of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ (copyByteArray# ba bOff mba 0# bsize s1)+ ) of (# _, r #) -> ArrayBase (# | (# 0#, r, steps, Dict #) #)+ {-# NOINLINE go #-}+ {-# INLINE fromBytes #-}++ readBytes mba bOff s0+ | steps <- cumulDims $ dims @ds+ , n <- cdTotalDim# steps+ , tbs <- byteSize (undefined :: t)+ , bsize <- tbs *# n+ = case newByteArray# bsize s0 of+ (# s1, mba1 #) -> case unsafeFreezeByteArray# mba1+ (copyMutableByteArray# mba bOff mba1 0# bsize s1) of+ (# s2, ba #) -> (# s2, ArrayBase (# | (# 0#, ba, steps, Dict #) #) #)+ {-# INLINE readBytes #-}++ writeBytes mba bOff (ArrayBase c)+ | tbs <- byteSize (undefined :: t) = case c of+ (# t | #) | W# n <- totalDim' @ds ->+ loop# bOff tbs (bOff +# word2Int# n *# tbs) (\i -> writeBytes mba i t)+ (# | (# offContent, arrContent, steps, _ #) #)+ | n <- cdTotalDim# steps->+ copyByteArray# arrContent (offContent *# tbs) mba bOff (n *# tbs)+ {-# INLINE writeBytes #-}++ readAddr addr s0+ | steps <- cumulDims $ dims @ds+ , n <- cdTotalDim# steps+ , tbs <- byteSize (undefined :: t)+ , bsize <- tbs *# n+ = case newByteArray# bsize s0 of+ (# s1, mba1 #) -> case unsafeFreezeByteArray# mba1+ (copyAddrToByteArray# addr mba1 0# bsize s1) of+ (# s2, ba #) -> (# s2, ArrayBase (# | (# 0# , ba, steps, Dict #) #) #)+ {-# INLINE readAddr #-}++ writeAddr (ArrayBase c) addr+ | tbs <- byteSize (undefined :: t) = case c of+ (# t | #) | W# n <- totalDim' @ds ->+ loop# 0# tbs (word2Int# n *# tbs) (\i -> writeAddr t (plusAddr# addr i))+ (# | (# offContent, arrContent, steps, _ #) #)+ | n <- cdTotalDim# steps ->+ copyByteArrayToAddr# arrContent (offContent *# tbs) addr (n *# tbs)+ {-# INLINE writeAddr #-}+++ byteSize _ = case totalDim' @ds of -- WARNING: slow!+ W# n -> byteSize (undefined :: t) *# word2Int# n+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign (undefined :: t)+ {-# INLINE byteAlign #-}++ byteOffset (ArrayBase a) = case a of+ (# _ | #) -> 0#+ (# | (# off, _, _, _ #) #) -> off *# byteSize (undefined :: t)+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | steps <- cumulDims $ dims @ds+ , n <- cdTotalDim# steps+ = ArrayBase (# | (# off *# n, ba, steps, Dict #) #)+ {-# INLINE indexArray #-}++++-- | Accumulates only idempotent operations!+-- Being applied to FromScalars, executes only once!+-- Here, idempotance means: assuming @f a b = g x@, @g (g x) = g x@+--+-- Also, I assume the sizes of arrays are the same.+--+-- Inside, this function uses foldr; thus, if the combining function is+-- lazy in the second argument, it may avoid some unnecessary work.+accumV2Idempotent :: a+ -> (t -> t -> a)+ -> (a -> a -> a)+ -> ArrayBase t ds -> ArrayBase t ds -> a+accumV2Idempotent x f comb+ (ArrayBase (# a | #))+ (ArrayBase (# b | #))+ = comb x (f a b)+accumV2Idempotent x f comb+ a@(ArrayBase (# | (# _, _, steps, Dict #) #))+ b@(ArrayBase (# | _ #))+ = foldr (comb . (\i -> f (ixOff i a) (ixOff i b))) x+ [0 .. fromIntegral (cdTotalDim steps) - 1]+accumV2Idempotent x f comb+ (ArrayBase (# a | #))+ b@(ArrayBase (# | (# _, _, steps, Dict #) #))+ = foldr (comb . (\i -> f a (ixOff i b))) x+ [0 .. fromIntegral (cdTotalDim steps) - 1]+accumV2Idempotent x f comb+ a@(ArrayBase (# | (# _, _, steps, Dict #) #))+ (ArrayBase (# b | #))+ = foldr (comb . (\i -> f (ixOff i a) b)) x+ [0 .. fromIntegral (cdTotalDim steps) - 1]+{-# INLINE accumV2Idempotent #-}+++mapV :: (t -> t) -> ArrayBase t ds -> ArrayBase t ds+mapV f (ArrayBase (# t | #))+ = ArrayBase (# f t | #)+mapV f x@(ArrayBase (# | (# offN, ba, steps, Dict #) #))+ | tbs <- byteSize (undefEl x)+ , n <- cdTotalDim# steps+ = case runRW#+ ( \s0 -> case newByteArray# (tbs *# n) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( loop1# n+ (\i -> writeArray mba i (f (indexArray ba (offN +# i)))) s1+ )+ ) of (# _, r #) -> ArrayBase (# | (# 0#, r, steps, Dict #) #)+{-# INLINE mapV #-}+++zipV :: (t -> t -> t)+ -> ArrayBase t ds -> ArrayBase t ds -> ArrayBase t ds+zipV f (ArrayBase (# x | #)) b = mapV (f x) b+zipV f a (ArrayBase (# y | #)) = mapV (`f` y) a+zipV f a@(ArrayBase (# | (# oa, ba, steps, Dict #) #))+ (ArrayBase (# | (# ob, bb, _, _ #) #))+ | n <- cdTotalDim# steps+ = case runRW#+ ( \s0 -> case newByteArray# (byteSize (undefEl a) *# n) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( loop1# n+ (\i -> writeArray mba i+ (f (indexArray ba (oa +# i))+ (indexArray bb (ob +# i))+ )+ ) s1+ )+ ) of (# _, r #) -> ArrayBase (# | (# 0#, r, steps, Dict #) #)+{-# INLINE zipV #-}+++-- TODO: to improve performance, I can either compare bytearrays using memcmp+-- or implement early termination if the first elements do not match.+-- On the other hand, hopefully @(&&)@ and @(||)@ ops take care of that.+instance Eq t => Eq (ArrayBase t ds) where+ {-# SPECIALIZE instance Eq (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Double ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance Eq (ArrayBase Word64 ds) #-}+ (==) = accumV2Idempotent True (==) (&&)+ (/=) = accumV2Idempotent False (/=) (||)++instance Ord t => ProductOrder (ArrayBase t ds) where+ {-# SPECIALIZE instance ProductOrder (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Double ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance ProductOrder (ArrayBase Word64 ds) #-}+ cmp = accumV2Idempotent PEQ (\x y -> fromOrdering (compare x y)) (<>)+ {-# INLINE cmp #-}++instance Ord t => Ord (NonTransitive.ProductOrd (ArrayBase t ds)) where+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Float ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Double ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Int ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Word ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Int8 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Int16 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Int32 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Int64 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Word8 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Word16 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Word32 ds)) #-}+ {-# SPECIALIZE instance Ord (NonTransitive.ProductOrd (ArrayBase Word64 ds)) #-}+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) = coerce (accumV2Idempotent True (>=) (&&))+ {-# INLINE (>=) #-}+ (<=) = coerce (accumV2Idempotent True (<=) (&&))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min = coerce (zipV min)+ {-# INLINE min #-}+ max = coerce (zipV max)+ {-# INLINE max #-}++instance Ord t => Ord (Partial.ProductOrd (ArrayBase t ds)) where+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Float ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Double ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Int ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Word ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Int8 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Int16 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Int32 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Int64 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Word8 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Word16 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Word32 ds)) #-}+ {-# SPECIALIZE instance Ord (Partial.ProductOrd (ArrayBase Word64 ds)) #-}+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) = coerce (accumV2Idempotent True (>=) (&&))+ {-# INLINE (>=) #-}+ (<=) = coerce (accumV2Idempotent True (<=) (&&))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min = coerce (zipV min)+ {-# INLINE min #-}+ max = coerce (zipV max)+ {-# INLINE max #-}++-- | Lexicographical ordering+instance Ord t => Ord (ArrayBase t ds) where+ {-# SPECIALIZE instance Ord (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Double ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance Ord (ArrayBase Word64 ds) #-}+ compare = accumV2Idempotent EQ compare (<>)+ {-# INLINE compare #-}++instance Bounded t => Bounded (ArrayBase t ds) where+ {-# SPECIALIZE instance Bounded (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance Bounded (ArrayBase Word64 ds) #-}+ maxBound = ArrayBase (# maxBound | #)+ minBound = ArrayBase (# minBound | #)++instance Num t => Num (ArrayBase t ds) where+ {-# SPECIALIZE instance Num (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Double ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance Num (ArrayBase Word64 ds) #-}+ (+) = zipV (+)+ {-# INLINE (+) #-}+ (-) = zipV (-)+ {-# INLINE (-) #-}+ (*) = zipV (*)+ {-# INLINE (*) #-}+ negate = mapV negate+ {-# INLINE negate #-}+ abs = mapV abs+ {-# INLINE abs #-}+ signum = mapV signum+ {-# INLINE signum #-}+ fromInteger i = ArrayBase (# fromInteger i | #)+ {-# INLINE fromInteger #-}++instance Fractional t => Fractional (ArrayBase t ds) where+ {-# SPECIALIZE instance Fractional (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance Fractional (ArrayBase Double ds) #-}+ (/) = zipV (/)+ {-# INLINE (/) #-}+ recip = mapV recip+ {-# INLINE recip #-}+ fromRational r = ArrayBase (# fromRational r | #)+ {-# INLINE fromRational #-}+++instance Floating t => Floating (ArrayBase t ds) where+ {-# SPECIALIZE instance Floating (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance Floating (ArrayBase Double ds) #-}+ pi = ArrayBase (# pi | #)+ {-# INLINE pi #-}+ exp = mapV exp+ {-# INLINE exp #-}+ log = mapV log+ {-# INLINE log #-}+ sqrt = mapV sqrt+ {-# INLINE sqrt #-}+ sin = mapV sin+ {-# INLINE sin #-}+ cos = mapV cos+ {-# INLINE cos #-}+ tan = mapV tan+ {-# INLINE tan #-}+ asin = mapV asin+ {-# INLINE asin #-}+ acos = mapV acos+ {-# INLINE acos #-}+ atan = mapV atan+ {-# INLINE atan #-}+ sinh = mapV sinh+ {-# INLINE sinh #-}+ cosh = mapV cosh+ {-# INLINE cosh #-}+ tanh = mapV tanh+ {-# INLINE tanh #-}+ (**) = zipV (**)+ {-# INLINE (**) #-}+ logBase = zipV logBase+ {-# INLINE logBase #-}+ asinh = mapV asinh+ {-# INLINE asinh #-}+ acosh = mapV acosh+ {-# INLINE acosh #-}+ atanh = mapV atanh+ {-# INLINE atanh #-}++instance PrimBytes t => PrimArray t (ArrayBase t ds) where+ {-# SPECIALIZE instance PrimArray Float (ArrayBase Float ds) #-}+ {-# SPECIALIZE instance PrimArray Double (ArrayBase Double ds) #-}+ {-# SPECIALIZE instance PrimArray Int (ArrayBase Int ds) #-}+ {-# SPECIALIZE instance PrimArray Word (ArrayBase Word ds) #-}+ {-# SPECIALIZE instance PrimArray Int8 (ArrayBase Int8 ds) #-}+ {-# SPECIALIZE instance PrimArray Int16 (ArrayBase Int16 ds) #-}+ {-# SPECIALIZE instance PrimArray Int32 (ArrayBase Int32 ds) #-}+ {-# SPECIALIZE instance PrimArray Int64 (ArrayBase Int64 ds) #-}+ {-# SPECIALIZE instance PrimArray Word8 (ArrayBase Word8 ds) #-}+ {-# SPECIALIZE instance PrimArray Word16 (ArrayBase Word16 ds) #-}+ {-# SPECIALIZE instance PrimArray Word32 (ArrayBase Word32 ds) #-}+ {-# SPECIALIZE instance PrimArray Word64 (ArrayBase Word64 ds) #-}++ broadcast t = ArrayBase (# t | #)+ {-# INLINE broadcast #-}++ ix# i (ArrayBase a) = case a of+ (# t | #) -> t+ (# | (# off, arr, _, _ #) #) -> indexArray arr (off +# i)+ {-# INLINE ix# #-}++ gen# steps f z0 = go (byteSize @t undefined *# n)+ where+ n = cdTotalDim# steps+ go bsize = case runRW#+ ( \s0 -> case newByteArray# bsize s0 of+ (# s1, mba #) -> case loop0 mba 0# z0 s1 of+ (# s2, z1 #) -> case unsafeFreezeByteArray# mba s2 of+ (# s3, ba #) -> (# s3, (# z1, ba #) #)+ ) of (# _, (# z1, ba #) #)+ -> (# z1, ArrayBase (# | (# 0# , ba, steps, Dict #) #) #)+ {-# NOINLINE go #-}+ loop0 mba i z s+ | isTrue# (i ==# n) = (# s, z #)+ | otherwise = case f z of+ (# z', x #) -> loop0 mba (i +# 1#) z' (writeArray mba i x s)+ {-# INLINE gen# #-}++ upd# steps i x (ArrayBase (# a | #)) = go (byteSize x)+ where+ n = cdTotalDim# steps+ go tbs = case runRW#+ ( \s0 -> case newByteArray# (tbs *# n) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ (writeArray mba i x+ (loop1# n (\j -> writeArray mba j a) s1)+ )+ ) of (# _, r #) -> ArrayBase (# | (# 0# , r, steps, Dict #) #)+ {-# NOINLINE go #-}+ upd# _ i x (ArrayBase (# | (# offN, ba, steps, Dict #) #))+ = go (byteSize x)+ where+ n = cdTotalDim# steps+ go tbs = case runRW#+ ( \s0 -> case newByteArray# (tbs *# n) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ (writeArray mba i x+ (copyByteArray# ba (offN *# tbs) mba 0# (tbs *# n) s1)+ )+ ) of (# _, r #) -> ArrayBase (# | (# 0#, r, steps, Dict #) #)+ {-# NOINLINE go #-}+ {-# INLINE upd# #-}++ arrayContent# (ArrayBase a) = case a of+ (# x | #) -> (# x | #)+ (# | (# off, arr, cd, _ #) #) -> (# | (# cd, off, arr #) #)+ {-# INLINE arrayContent# #-}++ offsetElems (ArrayBase a) = case a of+ (# _ | #) -> 0#+ (# | (# off, _, _, _ #) #) -> off+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims (ArrayBase a) = case a of+ (# t | #) -> Left t+ (# | (# _, _, steps, _ #) #) -> Right steps+ {-# INLINE uniqueOrCumulDims #-}++ fromElems steps off ba = ArrayBase (# | (# off, ba, steps, Dict #) #)+ {-# INLINE fromElems #-}+++loop# :: Int# -- ^ initial value+ -> Int# -- ^ step+ -> Int# -- ^ final value (LESS THAN condition)+ -> (Int# -> State# s -> State# s) -> State# s -> State# s+loop# n0 di n1 f = loop0 n0+ where+ loop0 i s | isTrue# (i >=# n1) = s+ | otherwise = loop0 (i +# di) (f i s)+{-# INLINE loop# #-}+++-- | Do something in a loop for int i from 0 to (n-1)+loop1# :: Int# -> (Int# -> State# s -> State# s) -> State# s -> State# s+loop1# n f = loop0 0#+ where+ loop0 i s | isTrue# (i ==# n) = s+ | otherwise = loop0 (i +# 1#) (f i s)+{-# INLINE loop1# #-}++undefEl :: ArrayBase t ds -> t+undefEl = const undefined
+ src-base/Numeric/DataFrame/Internal/Backend/Family/DoubleX2.hs view
@@ -0,0 +1,401 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.DataFrame.Internal.Backend.Family.DoubleX2 (DoubleX2 (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+++data DoubleX2 = DoubleX2# Double# Double#++-- | Since @Bounded@ is not implemented for floating point types, this instance+-- has an unresolvable constraint.+-- Nevetheless, it is good to have it here for nicer error messages.+instance Bounded Double => Bounded DoubleX2 where+ maxBound = case maxBound of D# x -> DoubleX2# x x+ minBound = case minBound of D# x -> DoubleX2# x x+++instance Eq DoubleX2 where++ DoubleX2# a1 a2 == DoubleX2# b1 b2 =+ isTrue#+ ( (a1 ==## b1)+ `andI#` (a2 ==## b2)+ )+ {-# INLINE (==) #-}++ DoubleX2# a1 a2 /= DoubleX2# b1 b2 =+ isTrue#+ ( (a1 /=## b1)+ `orI#` (a2 /=## b2)+ )+ {-# INLINE (/=) #-}++++cmp' :: Double# -> Double# -> PartialOrdering+cmp' a b+ | isTrue# (a >## b) = PGT+ | isTrue# (a <## b) = PLT+ | otherwise = PEQ++instance ProductOrder DoubleX2 where+ cmp (DoubleX2# a1 a2) (DoubleX2# b1 b2)+ = cmp' a1 b1 <> cmp' a2 b2+ {-# INLINE cmp #-}++instance Ord (NonTransitive.ProductOrd DoubleX2) where+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (NonTransitive.ProductOrd (DoubleX2# a1 a2))+ (NonTransitive.ProductOrd (DoubleX2# b1 b2)) = isTrue#+ ((a1 >=## b1) `andI#` (a2 >=## b2))+ {-# INLINE (>=) #-}+ (<=) (NonTransitive.ProductOrd (DoubleX2# a1 a2))+ (NonTransitive.ProductOrd (DoubleX2# b1 b2)) = isTrue#+ ((a1 <=## b1) `andI#` (a2 <=## b2))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (NonTransitive.ProductOrd (DoubleX2# a1 a2))+ (NonTransitive.ProductOrd (DoubleX2# b1 b2))+ = NonTransitive.ProductOrd+ ( DoubleX2#+ (if isTrue# (a1 >## b1) then b1 else a1)+ (if isTrue# (a2 >## b2) then b2 else a2)+ )+ {-# INLINE min #-}+ max (NonTransitive.ProductOrd (DoubleX2# a1 a2))+ (NonTransitive.ProductOrd (DoubleX2# b1 b2))+ = NonTransitive.ProductOrd+ ( DoubleX2#+ (if isTrue# (a1 <## b1) then b1 else a1)+ (if isTrue# (a2 <## b2) then b2 else a2)+ )+ {-# INLINE max #-}++instance Ord (Partial.ProductOrd DoubleX2) where+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (Partial.ProductOrd (DoubleX2# a1 a2))+ (Partial.ProductOrd (DoubleX2# b1 b2)) = isTrue#+ ((a1 >=## b1) `andI#` (a2 >=## b2))+ {-# INLINE (>=) #-}+ (<=) (Partial.ProductOrd (DoubleX2# a1 a2))+ (Partial.ProductOrd (DoubleX2# b1 b2)) = isTrue#+ ((a1 <=## b1) `andI#` (a2 <=## b2))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (Partial.ProductOrd (DoubleX2# a1 a2))+ (Partial.ProductOrd (DoubleX2# b1 b2))+ = Partial.ProductOrd+ ( DoubleX2#+ (if isTrue# (a1 >## b1) then b1 else a1)+ (if isTrue# (a2 >## b2) then b2 else a2)+ )+ {-# INLINE min #-}+ max (Partial.ProductOrd (DoubleX2# a1 a2))+ (Partial.ProductOrd (DoubleX2# b1 b2))+ = Partial.ProductOrd+ ( DoubleX2#+ (if isTrue# (a1 <## b1) then b1 else a1)+ (if isTrue# (a2 <## b2) then b2 else a2)+ )+ {-# INLINE max #-}++instance Ord DoubleX2 where+ DoubleX2# a1 a2 > DoubleX2# b1 b2+ | isTrue# (a1 >## b1) = True+ | isTrue# (a1 <## b1) = False+ | isTrue# (a2 >## b2) = True+ | otherwise = False+ {-# INLINE (>) #-}++ DoubleX2# a1 a2 < DoubleX2# b1 b2+ | isTrue# (a1 <## b1) = True+ | isTrue# (a1 >## b1) = False+ | isTrue# (a2 <## b2) = True+ | otherwise = False+ {-# INLINE (<) #-}++ DoubleX2# a1 a2 >= DoubleX2# b1 b2+ | isTrue# (a1 <## b1) = False+ | isTrue# (a1 >## b1) = True+ | isTrue# (a2 <## b2) = False+ | otherwise = True+ {-# INLINE (>=) #-}++ DoubleX2# a1 a2 <= DoubleX2# b1 b2+ | isTrue# (a1 >## b1) = False+ | isTrue# (a1 <## b1) = True+ | isTrue# (a2 >## b2) = False+ | otherwise = True+ {-# INLINE (<=) #-}++ compare (DoubleX2# a1 a2) (DoubleX2# b1 b2)+ | isTrue# (a1 >## b1) = GT+ | isTrue# (a1 <## b1) = LT+ | isTrue# (a2 >## b2) = GT+ | isTrue# (a2 <## b2) = LT+ | otherwise = EQ+ {-# INLINE compare #-}++++-- | element-wise operations for vectors+instance Num DoubleX2 where++ DoubleX2# a1 a2 + DoubleX2# b1 b2+ = DoubleX2# ((+##) a1 b1) ((+##) a2 b2)+ {-# INLINE (+) #-}++ DoubleX2# a1 a2 - DoubleX2# b1 b2+ = DoubleX2# ((-##) a1 b1) ((-##) a2 b2)+ {-# INLINE (-) #-}++ DoubleX2# a1 a2 * DoubleX2# b1 b2+ = DoubleX2# ((*##) a1 b1) ((*##) a2 b2)+ {-# INLINE (*) #-}++ negate (DoubleX2# a1 a2) = DoubleX2#+ (negateDouble# a1) (negateDouble# a2)+ {-# INLINE negate #-}++ abs (DoubleX2# a1 a2)+ = DoubleX2#+ (if isTrue# (a1 >=## 0.0##) then a1 else negateDouble# a1)+ (if isTrue# (a2 >=## 0.0##) then a2 else negateDouble# a2)+ {-# INLINE abs #-}++ signum (DoubleX2# a1 a2)+ = DoubleX2# (if isTrue# (a1 >## 0.0##)+ then 1.0##+ else if isTrue# (a1 <## 0.0##) then -1.0## else 0.0## )+ (if isTrue# (a2 >## 0.0##)+ then 1.0##+ else if isTrue# (a2 <## 0.0##) then -1.0## else 0.0## )+ {-# INLINE signum #-}++ fromInteger n = case fromInteger n of D# x -> DoubleX2# x x+ {-# INLINE fromInteger #-}++++instance Fractional DoubleX2 where++ DoubleX2# a1 a2 / DoubleX2# b1 b2 = DoubleX2#+ ((/##) a1 b1) ((/##) a2 b2)+ {-# INLINE (/) #-}++ recip (DoubleX2# a1 a2) = DoubleX2#+ ((/##) 1.0## a1) ((/##) 1.0## a2)+ {-# INLINE recip #-}++ fromRational r = case fromRational r of D# x -> DoubleX2# x x+ {-# INLINE fromRational #-}++++instance Floating DoubleX2 where++ pi = DoubleX2#+ 3.141592653589793238##+ 3.141592653589793238##+ {-# INLINE pi #-}++ exp (DoubleX2# a1 a2) = DoubleX2#+ (expDouble# a1) (expDouble# a2)+ {-# INLINE exp #-}++ log (DoubleX2# a1 a2) = DoubleX2#+ (logDouble# a1) (logDouble# a2)+ {-# INLINE log #-}++ sqrt (DoubleX2# a1 a2) = DoubleX2#+ (sqrtDouble# a1) (sqrtDouble# a2)+ {-# INLINE sqrt #-}++ sin (DoubleX2# a1 a2) = DoubleX2#+ (sinDouble# a1) (sinDouble# a2)+ {-# INLINE sin #-}++ cos (DoubleX2# a1 a2) = DoubleX2#+ (cosDouble# a1) (cosDouble# a2)+ {-# INLINE cos #-}++ tan (DoubleX2# a1 a2) = DoubleX2#+ (tanDouble# a1) (tanDouble# a2)+ {-# INLINE tan #-}++ asin (DoubleX2# a1 a2) = DoubleX2#+ (asinDouble# a1) (asinDouble# a2)+ {-# INLINE asin #-}++ acos (DoubleX2# a1 a2) = DoubleX2#+ (acosDouble# a1) (acosDouble# a2)+ {-# INLINE acos #-}++ atan (DoubleX2# a1 a2) = DoubleX2#+ (atanDouble# a1) (atanDouble# a2)+ {-# INLINE atan #-}++ sinh (DoubleX2# a1 a2) = DoubleX2#+ (sinhDouble# a1) (sinhDouble# a2)+ {-# INLINE sinh #-}++ cosh (DoubleX2# a1 a2) = DoubleX2#+ (coshDouble# a1) (coshDouble# a2)+ {-# INLINE cosh #-}++ tanh (DoubleX2# a1 a2) = DoubleX2#+ (tanhDouble# a1) (tanhDouble# a2)+ {-# INLINE tanh #-}++ DoubleX2# a1 a2 ** DoubleX2# b1 b2 = DoubleX2#+ ((**##) a1 b1) ((**##) a2 b2)+ {-# INLINE (**) #-}++ logBase x y = log y / log x+ {-# INLINE logBase #-}++ asinh x = log (x + sqrt (1.0+x*x))+ {-# INLINE asinh #-}++ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))+ {-# INLINE acosh #-}++ atanh x = 0.5 * log ((1.0+x) / (1.0-x))+ {-# INLINE atanh #-}++-- offset in bytes is S times bigger than offset in prim elements,+-- when S is power of two, this is equal to shift+#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 3#+#define ELEM_N 2++instance PrimBytes DoubleX2 where++ getBytes (DoubleX2# a1 a2) = case runRW#+ ( \s0 -> case newByteArray# (byteSize @DoubleX2 undefined) s0 of+ (# s1, marr #) -> case writeDoubleArray# marr 0# a1 s1 of+ s2 -> case writeDoubleArray# marr 1# a2 s2 of+ s3 -> unsafeFreezeByteArray# marr s3+ ) of (# _, a #) -> a+ {-# INLINE getBytes #-}++ fromBytes off arr+ | i <- BOFF_TO_PRIMOFF(off)+ = DoubleX2#+ (indexDoubleArray# arr i)+ (indexDoubleArray# arr (i +# 1#))+ {-# INLINE fromBytes #-}++ readBytes mba off s0+ | i <- BOFF_TO_PRIMOFF(off)+ = case readDoubleArray# mba i s0 of+ (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> (# s2, DoubleX2# a1 a2 #)+ {-# INLINE readBytes #-}++ writeBytes mba off (DoubleX2# a1 a2) s+ | i <- BOFF_TO_PRIMOFF(off)+ = writeDoubleArray# mba (i +# 1#) a2+ ( writeDoubleArray# mba i a1 s )+ {-# INLINE writeBytes #-}++ readAddr addr s0+ = case readDoubleOffAddr# addr 0# s0 of+ (# s1, a1 #) -> case readDoubleOffAddr# addr 1# s1 of+ (# s2, a2 #) -> (# s2, DoubleX2# a1 a2 #)+ {-# INLINE readAddr #-}++ writeAddr (DoubleX2# a1 a2) addr s+ = writeDoubleOffAddr# addr 1# a2+ ( writeDoubleOffAddr# addr 0# a1 s )+ {-# INLINE writeAddr #-}++ byteSize _ = byteSize @Double undefined *# ELEM_N#+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign @Double undefined+ {-# INLINE byteAlign #-}++ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | i <- off *# ELEM_N#+ = DoubleX2#+ (indexDoubleArray# ba i)+ (indexDoubleArray# ba (i +# 1#))+ {-# INLINE indexArray #-}++ readArray mba off s0+ | i <- off *# ELEM_N#+ = case readDoubleArray# mba i s0 of+ (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> (# s2, DoubleX2# a1 a2 #)+ {-# INLINE readArray #-}++ writeArray mba off (DoubleX2# a1 a2) s+ | i <- off *# ELEM_N#+ = writeDoubleArray# mba (i +# 1#) a2+ ( writeDoubleArray# mba i a1 s )+ {-# INLINE writeArray #-}+++instance PrimArray Double DoubleX2 where++ broadcast (D# x) = DoubleX2# x x+ {-# INLINE broadcast #-}++ ix# 0# (DoubleX2# a1 _) = D# a1+ ix# 1# (DoubleX2# _ a2) = D# a2+ ix# _ _ = undefined+ {-# INLINE ix# #-}++ gen# _ f s0 = case f s0 of+ (# s1, D# a1 #) -> case f s1 of+ (# s2, D# a2 #) -> (# s2, DoubleX2# a1 a2 #)+++ upd# _ 0# (D# q) (DoubleX2# _ y) = DoubleX2# q y+ upd# _ 1# (D# q) (DoubleX2# x _) = DoubleX2# x q+ upd# _ _ _ x = x+ {-# INLINE upd# #-}++ arrayContent# x = (# | (# CumulDims [ELEM_N, 1], 0#, getBytes x #) #)+ {-# INLINE arrayContent# #-}++ offsetElems _ = 0#+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims _ = Right (CumulDims [ELEM_N, 1])+ {-# INLINE uniqueOrCumulDims #-}++ fromElems _ off ba = DoubleX2#+ (indexDoubleArray# ba off)+ (indexDoubleArray# ba (off +# 1#))+ {-# INLINE fromElems #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family/DoubleX3.hs view
@@ -0,0 +1,436 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.DataFrame.Internal.Backend.Family.DoubleX3 (DoubleX3 (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+++data DoubleX3 = DoubleX3# Double# Double# Double#++-- | Since @Bounded@ is not implemented for floating point types, this instance+-- has an unresolvable constraint.+-- Nevetheless, it is good to have it here for nicer error messages.+instance Bounded Double => Bounded DoubleX3 where+ maxBound = case maxBound of D# x -> DoubleX3# x x x+ minBound = case minBound of D# x -> DoubleX3# x x x+++instance Eq DoubleX3 where++ DoubleX3# a1 a2 a3 == DoubleX3# b1 b2 b3 =+ isTrue#+ ( (a1 ==## b1)+ `andI#` (a2 ==## b2)+ `andI#` (a3 ==## b3)+ )+ {-# INLINE (==) #-}++ DoubleX3# a1 a2 a3 /= DoubleX3# b1 b2 b3 =+ isTrue#+ ( (a1 /=## b1)+ `orI#` (a2 /=## b2)+ `orI#` (a3 /=## b3)+ )+ {-# INLINE (/=) #-}++++cmp' :: Double# -> Double# -> PartialOrdering+cmp' a b+ | isTrue# (a >## b) = PGT+ | isTrue# (a <## b) = PLT+ | otherwise = PEQ++instance ProductOrder DoubleX3 where+ cmp (DoubleX3# a1 a2 a3) (DoubleX3# b1 b2 b3)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ {-# INLINE cmp #-}++instance Ord (NonTransitive.ProductOrd DoubleX3) where+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (NonTransitive.ProductOrd (DoubleX3# a1 a2 a3))+ (NonTransitive.ProductOrd (DoubleX3# b1 b2 b3)) = isTrue#+ ((a1 >=## b1) `andI#` (a2 >=## b2) `andI#` (a3 >=## b3))+ {-# INLINE (>=) #-}+ (<=) (NonTransitive.ProductOrd (DoubleX3# a1 a2 a3))+ (NonTransitive.ProductOrd (DoubleX3# b1 b2 b3)) = isTrue#+ ((a1 <=## b1) `andI#` (a2 <=## b2) `andI#` (a3 <=## b3))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (NonTransitive.ProductOrd (DoubleX3# a1 a2 a3))+ (NonTransitive.ProductOrd (DoubleX3# b1 b2 b3))+ = NonTransitive.ProductOrd+ ( DoubleX3#+ (if isTrue# (a1 >## b1) then b1 else a1)+ (if isTrue# (a2 >## b2) then b2 else a2)+ (if isTrue# (a3 >## b3) then b3 else a3)+ )+ {-# INLINE min #-}+ max (NonTransitive.ProductOrd (DoubleX3# a1 a2 a3))+ (NonTransitive.ProductOrd (DoubleX3# b1 b2 b3))+ = NonTransitive.ProductOrd+ ( DoubleX3#+ (if isTrue# (a1 <## b1) then b1 else a1)+ (if isTrue# (a2 <## b2) then b2 else a2)+ (if isTrue# (a3 <## b3) then b3 else a3)+ )+ {-# INLINE max #-}++instance Ord (Partial.ProductOrd DoubleX3) where+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (Partial.ProductOrd (DoubleX3# a1 a2 a3))+ (Partial.ProductOrd (DoubleX3# b1 b2 b3)) = isTrue#+ ((a1 >=## b1) `andI#` (a2 >=## b2) `andI#` (a3 >=## b3))+ {-# INLINE (>=) #-}+ (<=) (Partial.ProductOrd (DoubleX3# a1 a2 a3))+ (Partial.ProductOrd (DoubleX3# b1 b2 b3)) = isTrue#+ ((a1 <=## b1) `andI#` (a2 <=## b2) `andI#` (a3 <=## b3))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (Partial.ProductOrd (DoubleX3# a1 a2 a3))+ (Partial.ProductOrd (DoubleX3# b1 b2 b3))+ = Partial.ProductOrd+ ( DoubleX3#+ (if isTrue# (a1 >## b1) then b1 else a1)+ (if isTrue# (a2 >## b2) then b2 else a2)+ (if isTrue# (a3 >## b3) then b3 else a3)+ )+ {-# INLINE min #-}+ max (Partial.ProductOrd (DoubleX3# a1 a2 a3))+ (Partial.ProductOrd (DoubleX3# b1 b2 b3))+ = Partial.ProductOrd+ ( DoubleX3#+ (if isTrue# (a1 <## b1) then b1 else a1)+ (if isTrue# (a2 <## b2) then b2 else a2)+ (if isTrue# (a3 <## b3) then b3 else a3)+ )+ {-# INLINE max #-}++instance Ord DoubleX3 where+ DoubleX3# a1 a2 a3 > DoubleX3# b1 b2 b3+ | isTrue# (a1 >## b1) = True+ | isTrue# (a1 <## b1) = False+ | isTrue# (a2 >## b2) = True+ | isTrue# (a2 <## b2) = False+ | isTrue# (a3 >## b3) = True+ | otherwise = False+ {-# INLINE (>) #-}++ DoubleX3# a1 a2 a3 < DoubleX3# b1 b2 b3+ | isTrue# (a1 <## b1) = True+ | isTrue# (a1 >## b1) = False+ | isTrue# (a2 <## b2) = True+ | isTrue# (a2 >## b2) = False+ | isTrue# (a3 <## b3) = True+ | otherwise = False+ {-# INLINE (<) #-}++ DoubleX3# a1 a2 a3 >= DoubleX3# b1 b2 b3+ | isTrue# (a1 <## b1) = False+ | isTrue# (a1 >## b1) = True+ | isTrue# (a2 <## b2) = False+ | isTrue# (a2 >## b2) = True+ | isTrue# (a3 <## b3) = False+ | otherwise = True+ {-# INLINE (>=) #-}++ DoubleX3# a1 a2 a3 <= DoubleX3# b1 b2 b3+ | isTrue# (a1 >## b1) = False+ | isTrue# (a1 <## b1) = True+ | isTrue# (a2 >## b2) = False+ | isTrue# (a2 <## b2) = True+ | isTrue# (a3 >## b3) = False+ | otherwise = True+ {-# INLINE (<=) #-}++ compare (DoubleX3# a1 a2 a3) (DoubleX3# b1 b2 b3)+ | isTrue# (a1 >## b1) = GT+ | isTrue# (a1 <## b1) = LT+ | isTrue# (a2 >## b2) = GT+ | isTrue# (a2 <## b2) = LT+ | isTrue# (a3 >## b3) = GT+ | isTrue# (a3 <## b3) = LT+ | otherwise = EQ+ {-# INLINE compare #-}+++++-- | element-wise operations for vectors+instance Num DoubleX3 where++ DoubleX3# a1 a2 a3 + DoubleX3# b1 b2 b3+ = DoubleX3# ((+##) a1 b1) ((+##) a2 b2) ((+##) a3 b3)+ {-# INLINE (+) #-}++ DoubleX3# a1 a2 a3 - DoubleX3# b1 b2 b3+ = DoubleX3# ((-##) a1 b1) ((-##) a2 b2) ((-##) a3 b3)+ {-# INLINE (-) #-}++ DoubleX3# a1 a2 a3 * DoubleX3# b1 b2 b3+ = DoubleX3# ((*##) a1 b1) ((*##) a2 b2) ((*##) a3 b3)+ {-# INLINE (*) #-}++ negate (DoubleX3# a1 a2 a3) = DoubleX3#+ (negateDouble# a1) (negateDouble# a2) (negateDouble# a3)+ {-# INLINE negate #-}++ abs (DoubleX3# a1 a2 a3)+ = DoubleX3#+ (if isTrue# (a1 >=## 0.0##) then a1 else negateDouble# a1)+ (if isTrue# (a2 >=## 0.0##) then a2 else negateDouble# a2)+ (if isTrue# (a3 >=## 0.0##) then a3 else negateDouble# a3)+ {-# INLINE abs #-}++ signum (DoubleX3# a1 a2 a3)+ = DoubleX3# (if isTrue# (a1 >## 0.0##)+ then 1.0##+ else if isTrue# (a1 <## 0.0##) then -1.0## else 0.0## )+ (if isTrue# (a2 >## 0.0##)+ then 1.0##+ else if isTrue# (a2 <## 0.0##) then -1.0## else 0.0## )+ (if isTrue# (a3 >## 0.0##)+ then 1.0##+ else if isTrue# (a3 <## 0.0##) then -1.0## else 0.0## )+ {-# INLINE signum #-}++ fromInteger n = case fromInteger n of D# x -> DoubleX3# x x x+ {-# INLINE fromInteger #-}++++instance Fractional DoubleX3 where++ DoubleX3# a1 a2 a3 / DoubleX3# b1 b2 b3 = DoubleX3#+ ((/##) a1 b1) ((/##) a2 b2) ((/##) a3 b3)+ {-# INLINE (/) #-}++ recip (DoubleX3# a1 a2 a3) = DoubleX3#+ ((/##) 1.0## a1) ((/##) 1.0## a2) ((/##) 1.0## a3)+ {-# INLINE recip #-}++ fromRational r = case fromRational r of D# x -> DoubleX3# x x x+ {-# INLINE fromRational #-}++++instance Floating DoubleX3 where++ pi = DoubleX3#+ 3.141592653589793238##+ 3.141592653589793238##+ 3.141592653589793238##+ {-# INLINE pi #-}++ exp (DoubleX3# a1 a2 a3) = DoubleX3#+ (expDouble# a1) (expDouble# a2) (expDouble# a3)+ {-# INLINE exp #-}++ log (DoubleX3# a1 a2 a3) = DoubleX3#+ (logDouble# a1) (logDouble# a2) (logDouble# a3)+ {-# INLINE log #-}++ sqrt (DoubleX3# a1 a2 a3) = DoubleX3#+ (sqrtDouble# a1) (sqrtDouble# a2) (sqrtDouble# a3)+ {-# INLINE sqrt #-}++ sin (DoubleX3# a1 a2 a3) = DoubleX3#+ (sinDouble# a1) (sinDouble# a2) (sinDouble# a3)+ {-# INLINE sin #-}++ cos (DoubleX3# a1 a2 a3) = DoubleX3#+ (cosDouble# a1) (cosDouble# a2) (cosDouble# a3)+ {-# INLINE cos #-}++ tan (DoubleX3# a1 a2 a3) = DoubleX3#+ (tanDouble# a1) (tanDouble# a2) (tanDouble# a3)+ {-# INLINE tan #-}++ asin (DoubleX3# a1 a2 a3) = DoubleX3#+ (asinDouble# a1) (asinDouble# a2) (asinDouble# a3)+ {-# INLINE asin #-}++ acos (DoubleX3# a1 a2 a3) = DoubleX3#+ (acosDouble# a1) (acosDouble# a2) (acosDouble# a3)+ {-# INLINE acos #-}++ atan (DoubleX3# a1 a2 a3) = DoubleX3#+ (atanDouble# a1) (atanDouble# a2) (atanDouble# a3)+ {-# INLINE atan #-}++ sinh (DoubleX3# a1 a2 a3) = DoubleX3#+ (sinhDouble# a1) (sinhDouble# a2) (sinhDouble# a3)+ {-# INLINE sinh #-}++ cosh (DoubleX3# a1 a2 a3) = DoubleX3#+ (coshDouble# a1) (coshDouble# a2) (coshDouble# a3)+ {-# INLINE cosh #-}++ tanh (DoubleX3# a1 a2 a3) = DoubleX3#+ (tanhDouble# a1) (tanhDouble# a2) (tanhDouble# a3)+ {-# INLINE tanh #-}++ DoubleX3# a1 a2 a3 ** DoubleX3# b1 b2 b3 = DoubleX3#+ ((**##) a1 b1) ((**##) a2 b2) ((**##) a3 b3)+ {-# INLINE (**) #-}++ logBase x y = log y / log x+ {-# INLINE logBase #-}++ asinh x = log (x + sqrt (1.0+x*x))+ {-# INLINE asinh #-}++ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))+ {-# INLINE acosh #-}++ atanh x = 0.5 * log ((1.0+x) / (1.0-x))+ {-# INLINE atanh #-}++-- offset in bytes is S times bigger than offset in prim elements,+-- when S is power of two, this is equal to shift+#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 3#+#define ELEM_N 3++instance PrimBytes DoubleX3 where++ getBytes (DoubleX3# a1 a2 a3) = case runRW#+ ( \s0 -> case newByteArray# (byteSize @DoubleX3 undefined) s0 of+ (# s1, marr #) -> case writeDoubleArray# marr 0# a1 s1 of+ s2 -> case writeDoubleArray# marr 1# a2 s2 of+ s3 -> case writeDoubleArray# marr 2# a3 s3 of+ s4 -> unsafeFreezeByteArray# marr s4+ ) of (# _, a #) -> a+ {-# INLINE getBytes #-}++ fromBytes off arr+ | i <- BOFF_TO_PRIMOFF(off)+ = DoubleX3#+ (indexDoubleArray# arr i)+ (indexDoubleArray# arr (i +# 1#))+ (indexDoubleArray# arr (i +# 2#))+ {-# INLINE fromBytes #-}++ readBytes mba off s0+ | i <- BOFF_TO_PRIMOFF(off)+ = case readDoubleArray# mba i s0 of+ (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)+ {-# INLINE readBytes #-}++ writeBytes mba off (DoubleX3# a1 a2 a3) s+ | i <- BOFF_TO_PRIMOFF(off)+ = writeDoubleArray# mba (i +# 2#) a3+ ( writeDoubleArray# mba (i +# 1#) a2+ ( writeDoubleArray# mba i a1 s ))+ {-# INLINE writeBytes #-}++ readAddr addr s0+ = case readDoubleOffAddr# addr 0# s0 of+ (# s1, a1 #) -> case readDoubleOffAddr# addr 1# s1 of+ (# s2, a2 #) -> case readDoubleOffAddr# addr 2# s2 of+ (# s3, a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)+ {-# INLINE readAddr #-}++ writeAddr (DoubleX3# a1 a2 a3) addr s+ = writeDoubleOffAddr# addr 2# a3+ ( writeDoubleOffAddr# addr 1# a2+ ( writeDoubleOffAddr# addr 0# a1 s ))+ {-# INLINE writeAddr #-}++ byteSize _ = byteSize @Double undefined *# ELEM_N#+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign @Double undefined+ {-# INLINE byteAlign #-}++ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | i <- off *# ELEM_N#+ = DoubleX3#+ (indexDoubleArray# ba i)+ (indexDoubleArray# ba (i +# 1#))+ (indexDoubleArray# ba (i +# 2#))+ {-# INLINE indexArray #-}++ readArray mba off s0+ | i <- off *# ELEM_N#+ = case readDoubleArray# mba i s0 of+ (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)+ {-# INLINE readArray #-}++ writeArray mba off (DoubleX3# a1 a2 a3) s+ | i <- off *# ELEM_N#+ = writeDoubleArray# mba (i +# 2#) a3+ ( writeDoubleArray# mba (i +# 1#) a2+ ( writeDoubleArray# mba i a1 s ))+ {-# INLINE writeArray #-}+++instance PrimArray Double DoubleX3 where++ broadcast (D# x) = DoubleX3# x x x+ {-# INLINE broadcast #-}++ ix# 0# (DoubleX3# a1 _ _) = D# a1+ ix# 1# (DoubleX3# _ a2 _) = D# a2+ ix# 2# (DoubleX3# _ _ a3) = D# a3+ ix# _ _ = undefined+ {-# INLINE ix# #-}++ gen# _ f s0 = case f s0 of+ (# s1, D# a1 #) -> case f s1 of+ (# s2, D# a2 #) -> case f s2 of+ (# s3, D# a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)+++ upd# _ 0# (D# q) (DoubleX3# _ y z) = DoubleX3# q y z+ upd# _ 1# (D# q) (DoubleX3# x _ z) = DoubleX3# x q z+ upd# _ 2# (D# q) (DoubleX3# x y _) = DoubleX3# x y q+ upd# _ _ _ x = x+ {-# INLINE upd# #-}++ arrayContent# x = (# | (# CumulDims [ELEM_N, 1], 0#, getBytes x #) #)+ {-# INLINE arrayContent# #-}++ offsetElems _ = 0#+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims _ = Right (CumulDims [ELEM_N, 1])+ {-# INLINE uniqueOrCumulDims #-}++ fromElems _ off ba = DoubleX3#+ (indexDoubleArray# ba off)+ (indexDoubleArray# ba (off +# 1#))+ (indexDoubleArray# ba (off +# 2#))+ {-# INLINE fromElems #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family/DoubleX4.hs view
@@ -0,0 +1,467 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.DataFrame.Internal.Backend.Family.DoubleX4 (DoubleX4 (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+++data DoubleX4 = DoubleX4# Double# Double# Double# Double#++-- | Since @Bounded@ is not implemented for floating point types, this instance+-- has an unresolvable constraint.+-- Nevetheless, it is good to have it here for nicer error messages.+instance Bounded Double => Bounded DoubleX4 where+ maxBound = case maxBound of D# x -> DoubleX4# x x x x+ minBound = case minBound of D# x -> DoubleX4# x x x x+++instance Eq DoubleX4 where++ DoubleX4# a1 a2 a3 a4 == DoubleX4# b1 b2 b3 b4 =+ isTrue#+ ( (a1 ==## b1)+ `andI#` (a2 ==## b2)+ `andI#` (a3 ==## b3)+ `andI#` (a4 ==## b4)+ )+ {-# INLINE (==) #-}++ DoubleX4# a1 a2 a3 a4 /= DoubleX4# b1 b2 b3 b4 =+ isTrue#+ ( (a1 /=## b1)+ `orI#` (a2 /=## b2)+ `orI#` (a3 /=## b3)+ `orI#` (a4 /=## b4)+ )+ {-# INLINE (/=) #-}++cmp' :: Double# -> Double# -> PartialOrdering+cmp' a b+ | isTrue# (a >## b) = PGT+ | isTrue# (a <## b) = PLT+ | otherwise = PEQ++instance ProductOrder DoubleX4 where+ cmp (DoubleX4# a1 a2 a3 a4) (DoubleX4# b1 b2 b3 b4)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3 <> cmp' a4 b4+ {-# INLINE cmp #-}++instance Ord (NonTransitive.ProductOrd DoubleX4) where+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (NonTransitive.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (DoubleX4# b1 b2 b3 b4)) = isTrue#+ ((a1 >=## b1) `andI#` (a2 >=## b2) `andI#` (a3 >=## b3) `andI#` (a4 >=## b4))+ {-# INLINE (>=) #-}+ (<=) (NonTransitive.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (DoubleX4# b1 b2 b3 b4)) = isTrue#+ ((a1 <=## b1) `andI#` (a2 <=## b2) `andI#` (a3 <=## b3) `andI#` (a4 <=## b4))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (NonTransitive.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (DoubleX4# b1 b2 b3 b4))+ = NonTransitive.ProductOrd+ ( DoubleX4#+ (if isTrue# (a1 >## b1) then b1 else a1)+ (if isTrue# (a2 >## b2) then b2 else a2)+ (if isTrue# (a3 >## b3) then b3 else a3)+ (if isTrue# (a4 >## b4) then b4 else a4)+ )+ {-# INLINE min #-}+ max (NonTransitive.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (DoubleX4# b1 b2 b3 b4))+ = NonTransitive.ProductOrd+ ( DoubleX4#+ (if isTrue# (a1 <## b1) then b1 else a1)+ (if isTrue# (a2 <## b2) then b2 else a2)+ (if isTrue# (a3 <## b3) then b3 else a3)+ (if isTrue# (a4 <## b4) then b4 else a4)+ )+ {-# INLINE max #-}++instance Ord (Partial.ProductOrd DoubleX4) where+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (Partial.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (Partial.ProductOrd (DoubleX4# b1 b2 b3 b4)) = isTrue#+ ((a1 >=## b1) `andI#` (a2 >=## b2) `andI#` (a3 >=## b3) `andI#` (a4 >=## b4))+ {-# INLINE (>=) #-}+ (<=) (Partial.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (Partial.ProductOrd (DoubleX4# b1 b2 b3 b4)) = isTrue#+ ((a1 <=## b1) `andI#` (a2 <=## b2) `andI#` (a3 <=## b3) `andI#` (a4 <=## b4))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (Partial.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (Partial.ProductOrd (DoubleX4# b1 b2 b3 b4))+ = Partial.ProductOrd+ ( DoubleX4#+ (if isTrue# (a1 >## b1) then b1 else a1)+ (if isTrue# (a2 >## b2) then b2 else a2)+ (if isTrue# (a3 >## b3) then b3 else a3)+ (if isTrue# (a4 >## b4) then b4 else a4)+ )+ {-# INLINE min #-}+ max (Partial.ProductOrd (DoubleX4# a1 a2 a3 a4))+ (Partial.ProductOrd (DoubleX4# b1 b2 b3 b4))+ = Partial.ProductOrd+ ( DoubleX4#+ (if isTrue# (a1 <## b1) then b1 else a1)+ (if isTrue# (a2 <## b2) then b2 else a2)+ (if isTrue# (a3 <## b3) then b3 else a3)+ (if isTrue# (a4 <## b4) then b4 else a4)+ )+ {-# INLINE max #-}++instance Ord DoubleX4 where+ DoubleX4# a1 a2 a3 a4 > DoubleX4# b1 b2 b3 b4+ | isTrue# (a1 >## b1) = True+ | isTrue# (a1 <## b1) = False+ | isTrue# (a2 >## b2) = True+ | isTrue# (a2 <## b2) = False+ | isTrue# (a3 >## b3) = True+ | isTrue# (a3 <## b3) = False+ | isTrue# (a4 >## b4) = True+ | otherwise = False+ {-# INLINE (>) #-}++ DoubleX4# a1 a2 a3 a4 < DoubleX4# b1 b2 b3 b4+ | isTrue# (a1 <## b1) = True+ | isTrue# (a1 >## b1) = False+ | isTrue# (a2 <## b2) = True+ | isTrue# (a2 >## b2) = False+ | isTrue# (a3 <## b3) = True+ | isTrue# (a3 >## b3) = False+ | isTrue# (a4 <## b4) = True+ | otherwise = False+ {-# INLINE (<) #-}++ DoubleX4# a1 a2 a3 a4 >= DoubleX4# b1 b2 b3 b4+ | isTrue# (a1 <## b1) = False+ | isTrue# (a1 >## b1) = True+ | isTrue# (a2 <## b2) = False+ | isTrue# (a2 >## b2) = True+ | isTrue# (a3 <## b3) = False+ | isTrue# (a3 >## b3) = True+ | isTrue# (a4 <## b4) = False+ | otherwise = True+ {-# INLINE (>=) #-}++ DoubleX4# a1 a2 a3 a4 <= DoubleX4# b1 b2 b3 b4+ | isTrue# (a1 >## b1) = False+ | isTrue# (a1 <## b1) = True+ | isTrue# (a2 >## b2) = False+ | isTrue# (a2 <## b2) = True+ | isTrue# (a3 >## b3) = False+ | isTrue# (a3 <## b3) = True+ | isTrue# (a4 >## b4) = False+ | otherwise = True+ {-# INLINE (<=) #-}++ compare (DoubleX4# a1 a2 a3 a4) (DoubleX4# b1 b2 b3 b4)+ | isTrue# (a1 >## b1) = GT+ | isTrue# (a1 <## b1) = LT+ | isTrue# (a2 >## b2) = GT+ | isTrue# (a2 <## b2) = LT+ | isTrue# (a3 >## b3) = GT+ | isTrue# (a3 <## b3) = LT+ | isTrue# (a4 >## b4) = GT+ | isTrue# (a4 <## b4) = LT+ | otherwise = EQ+ {-# INLINE compare #-}++++-- | element-wise operations for vectors+instance Num DoubleX4 where++ DoubleX4# a1 a2 a3 a4 + DoubleX4# b1 b2 b3 b4+ = DoubleX4# ((+##) a1 b1) ((+##) a2 b2) ((+##) a3 b3) ((+##) a4 b4)+ {-# INLINE (+) #-}++ DoubleX4# a1 a2 a3 a4 - DoubleX4# b1 b2 b3 b4+ = DoubleX4# ((-##) a1 b1) ((-##) a2 b2) ((-##) a3 b3) ((-##) a4 b4)+ {-# INLINE (-) #-}++ DoubleX4# a1 a2 a3 a4 * DoubleX4# b1 b2 b3 b4+ = DoubleX4# ((*##) a1 b1) ((*##) a2 b2) ((*##) a3 b3) ((*##) a4 b4)+ {-# INLINE (*) #-}++ negate (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (negateDouble# a1) (negateDouble# a2) (negateDouble# a3) (negateDouble# a4)+ {-# INLINE negate #-}++ abs (DoubleX4# a1 a2 a3 a4)+ = DoubleX4#+ (if isTrue# (a1 >=## 0.0##) then a1 else negateDouble# a1)+ (if isTrue# (a2 >=## 0.0##) then a2 else negateDouble# a2)+ (if isTrue# (a3 >=## 0.0##) then a3 else negateDouble# a3)+ (if isTrue# (a4 >=## 0.0##) then a4 else negateDouble# a4)+ {-# INLINE abs #-}++ signum (DoubleX4# a1 a2 a3 a4)+ = DoubleX4# (if isTrue# (a1 >## 0.0##)+ then 1.0##+ else if isTrue# (a1 <## 0.0##) then -1.0## else 0.0## )+ (if isTrue# (a2 >## 0.0##)+ then 1.0##+ else if isTrue# (a2 <## 0.0##) then -1.0## else 0.0## )+ (if isTrue# (a3 >## 0.0##)+ then 1.0##+ else if isTrue# (a3 <## 0.0##) then -1.0## else 0.0## )+ (if isTrue# (a4 >## 0.0##)+ then 1.0##+ else if isTrue# (a4 <## 0.0##) then -1.0## else 0.0## )+ {-# INLINE signum #-}++ fromInteger n = case fromInteger n of D# x -> DoubleX4# x x x x+ {-# INLINE fromInteger #-}++++instance Fractional DoubleX4 where++ DoubleX4# a1 a2 a3 a4 / DoubleX4# b1 b2 b3 b4 = DoubleX4#+ ((/##) a1 b1) ((/##) a2 b2) ((/##) a3 b3) ((/##) a4 b4)+ {-# INLINE (/) #-}++ recip (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ ((/##) 1.0## a1) ((/##) 1.0## a2) ((/##) 1.0## a3) ((/##) 1.0## a4)+ {-# INLINE recip #-}++ fromRational r = case fromRational r of D# x -> DoubleX4# x x x x+ {-# INLINE fromRational #-}++++instance Floating DoubleX4 where++ pi = DoubleX4#+ 3.141592653589793238##+ 3.141592653589793238##+ 3.141592653589793238##+ 3.141592653589793238##+ {-# INLINE pi #-}++ exp (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (expDouble# a1) (expDouble# a2) (expDouble# a3) (expDouble# a4)+ {-# INLINE exp #-}++ log (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (logDouble# a1) (logDouble# a2) (logDouble# a3) (logDouble# a4)+ {-# INLINE log #-}++ sqrt (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (sqrtDouble# a1) (sqrtDouble# a2) (sqrtDouble# a3) (sqrtDouble# a4)+ {-# INLINE sqrt #-}++ sin (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (sinDouble# a1) (sinDouble# a2) (sinDouble# a3) (sinDouble# a4)+ {-# INLINE sin #-}++ cos (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (cosDouble# a1) (cosDouble# a2) (cosDouble# a3) (cosDouble# a4)+ {-# INLINE cos #-}++ tan (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (tanDouble# a1) (tanDouble# a2) (tanDouble# a3) (tanDouble# a4)+ {-# INLINE tan #-}++ asin (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (asinDouble# a1) (asinDouble# a2) (asinDouble# a3) (asinDouble# a4)+ {-# INLINE asin #-}++ acos (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (acosDouble# a1) (acosDouble# a2) (acosDouble# a3) (acosDouble# a4)+ {-# INLINE acos #-}++ atan (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (atanDouble# a1) (atanDouble# a2) (atanDouble# a3) (atanDouble# a4)+ {-# INLINE atan #-}++ sinh (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (sinhDouble# a1) (sinhDouble# a2) (sinhDouble# a3) (sinhDouble# a4)+ {-# INLINE sinh #-}++ cosh (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (coshDouble# a1) (coshDouble# a2) (coshDouble# a3) (coshDouble# a4)+ {-# INLINE cosh #-}++ tanh (DoubleX4# a1 a2 a3 a4) = DoubleX4#+ (tanhDouble# a1) (tanhDouble# a2) (tanhDouble# a3) (tanhDouble# a4)+ {-# INLINE tanh #-}++ DoubleX4# a1 a2 a3 a4 ** DoubleX4# b1 b2 b3 b4 = DoubleX4#+ ((**##) a1 b1) ((**##) a2 b2) ((**##) a3 b3) ((**##) a4 b4)+ {-# INLINE (**) #-}++ logBase x y = log y / log x+ {-# INLINE logBase #-}++ asinh x = log (x + sqrt (1.0+x*x))+ {-# INLINE asinh #-}++ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))+ {-# INLINE acosh #-}++ atanh x = 0.5 * log ((1.0+x) / (1.0-x))+ {-# INLINE atanh #-}++-- offset in bytes is S times bigger than offset in prim elements,+-- when S is power of two, this is equal to shift+#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 3#+#define ELEM_N 4++instance PrimBytes DoubleX4 where++ getBytes (DoubleX4# a1 a2 a3 a4) = case runRW#+ ( \s0 -> case newByteArray# (byteSize @DoubleX4 undefined) s0 of+ (# s1, marr #) -> case writeDoubleArray# marr 0# a1 s1 of+ s2 -> case writeDoubleArray# marr 1# a2 s2 of+ s3 -> case writeDoubleArray# marr 2# a3 s3 of+ s4 -> case writeDoubleArray# marr 3# a4 s4 of+ s5 -> unsafeFreezeByteArray# marr s5+ ) of (# _, a #) -> a+ {-# INLINE getBytes #-}++ fromBytes off arr+ | i <- BOFF_TO_PRIMOFF(off)+ = DoubleX4#+ (indexDoubleArray# arr i)+ (indexDoubleArray# arr (i +# 1#))+ (indexDoubleArray# arr (i +# 2#))+ (indexDoubleArray# arr (i +# 3#))+ {-# INLINE fromBytes #-}++ readBytes mba off s0+ | i <- BOFF_TO_PRIMOFF(off)+ = case readDoubleArray# mba i s0 of+ (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> case readDoubleArray# mba (i +# 3#) s3 of+ (# s4, a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)+ {-# INLINE readBytes #-}++ writeBytes mba off (DoubleX4# a1 a2 a3 a4) s+ | i <- BOFF_TO_PRIMOFF(off)+ = writeDoubleArray# mba (i +# 3#) a4+ ( writeDoubleArray# mba (i +# 2#) a3+ ( writeDoubleArray# mba (i +# 1#) a2+ ( writeDoubleArray# mba i a1 s )))+ {-# INLINE writeBytes #-}++ readAddr addr s0+ = case readDoubleOffAddr# addr 0# s0 of+ (# s1, a1 #) -> case readDoubleOffAddr# addr 1# s1 of+ (# s2, a2 #) -> case readDoubleOffAddr# addr 2# s2 of+ (# s3, a3 #) -> case readDoubleOffAddr# addr 3# s3 of+ (# s4, a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)+ {-# INLINE readAddr #-}++ writeAddr (DoubleX4# a1 a2 a3 a4) addr s+ = writeDoubleOffAddr# addr 3# a4+ ( writeDoubleOffAddr# addr 2# a3+ ( writeDoubleOffAddr# addr 1# a2+ ( writeDoubleOffAddr# addr 0# a1 s )))+ {-# INLINE writeAddr #-}++ byteSize _ = byteSize @Double undefined *# ELEM_N#+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign @Double undefined+ {-# INLINE byteAlign #-}++ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | i <- off *# ELEM_N#+ = DoubleX4#+ (indexDoubleArray# ba i)+ (indexDoubleArray# ba (i +# 1#))+ (indexDoubleArray# ba (i +# 2#))+ (indexDoubleArray# ba (i +# 3#))+ {-# INLINE indexArray #-}++ readArray mba off s0+ | i <- off *# ELEM_N#+ = case readDoubleArray# mba i s0 of+ (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> case readDoubleArray# mba (i +# 3#) s3 of+ (# s4, a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)+ {-# INLINE readArray #-}++ writeArray mba off (DoubleX4# a1 a2 a3 a4) s+ | i <- off *# ELEM_N#+ = writeDoubleArray# mba (i +# 3#) a4+ ( writeDoubleArray# mba (i +# 2#) a3+ ( writeDoubleArray# mba (i +# 1#) a2+ ( writeDoubleArray# mba i a1 s )))+ {-# INLINE writeArray #-}+++instance PrimArray Double DoubleX4 where++ broadcast (D# x) = DoubleX4# x x x x+ {-# INLINE broadcast #-}++ ix# 0# (DoubleX4# a1 _ _ _) = D# a1+ ix# 1# (DoubleX4# _ a2 _ _) = D# a2+ ix# 2# (DoubleX4# _ _ a3 _) = D# a3+ ix# 3# (DoubleX4# _ _ _ a4) = D# a4+ ix# _ _ = undefined+ {-# INLINE ix# #-}++ gen# _ f s0 = case f s0 of+ (# s1, D# a1 #) -> case f s1 of+ (# s2, D# a2 #) -> case f s2 of+ (# s3, D# a3 #) -> case f s3 of+ (# s4, D# a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)+++ upd# _ 0# (D# q) (DoubleX4# _ y z w) = DoubleX4# q y z w+ upd# _ 1# (D# q) (DoubleX4# x _ z w) = DoubleX4# x q z w+ upd# _ 2# (D# q) (DoubleX4# x y _ w) = DoubleX4# x y q w+ upd# _ 3# (D# q) (DoubleX4# x y z _) = DoubleX4# x y z q+ upd# _ _ _ x = x+ {-# INLINE upd# #-}++ arrayContent# x = (# | (# CumulDims [ELEM_N, 1], 0#, getBytes x #) #)+ {-# INLINE arrayContent# #-}++ offsetElems _ = 0#+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims _ = Right (CumulDims [ELEM_N, 1])+ {-# INLINE uniqueOrCumulDims #-}++ fromElems _ off ba = DoubleX4#+ (indexDoubleArray# ba off)+ (indexDoubleArray# ba (off +# 1#))+ (indexDoubleArray# ba (off +# 2#))+ (indexDoubleArray# ba (off +# 3#))+ {-# INLINE fromElems #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family/FloatX2.hs view
@@ -0,0 +1,401 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.DataFrame.Internal.Backend.Family.FloatX2 (FloatX2 (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+++data FloatX2 = FloatX2# Float# Float#++-- | Since @Bounded@ is not implemented for floating point types, this instance+-- has an unresolvable constraint.+-- Nevetheless, it is good to have it here for nicer error messages.+instance Bounded Float => Bounded FloatX2 where+ maxBound = case maxBound of F# x -> FloatX2# x x+ minBound = case minBound of F# x -> FloatX2# x x+++instance Eq FloatX2 where++ FloatX2# a1 a2 == FloatX2# b1 b2 =+ isTrue#+ ( (a1 `eqFloat#` b1)+ `andI#` (a2 `eqFloat#` b2)+ )+ {-# INLINE (==) #-}++ FloatX2# a1 a2 /= FloatX2# b1 b2 =+ isTrue#+ ( (a1 `neFloat#` b1)+ `orI#` (a2 `neFloat#` b2)+ )+ {-# INLINE (/=) #-}++++cmp' :: Float# -> Float# -> PartialOrdering+cmp' a b+ | isTrue# (a `gtFloat#` b) = PGT+ | isTrue# (a `ltFloat#` b) = PLT+ | otherwise = PEQ++instance ProductOrder FloatX2 where+ cmp (FloatX2# a1 a2) (FloatX2# b1 b2)+ = cmp' a1 b1 <> cmp' a2 b2+ {-# INLINE cmp #-}++instance Ord (NonTransitive.ProductOrd FloatX2) where+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (NonTransitive.ProductOrd (FloatX2# a1 a2))+ (NonTransitive.ProductOrd (FloatX2# b1 b2)) = isTrue#+ ((a1 `geFloat#` b1) `andI#` (a2 `geFloat#` b2))+ {-# INLINE (>=) #-}+ (<=) (NonTransitive.ProductOrd (FloatX2# a1 a2))+ (NonTransitive.ProductOrd (FloatX2# b1 b2)) = isTrue#+ ((a1 `leFloat#` b1) `andI#` (a2 `leFloat#` b2))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (NonTransitive.ProductOrd (FloatX2# a1 a2))+ (NonTransitive.ProductOrd (FloatX2# b1 b2))+ = NonTransitive.ProductOrd+ ( FloatX2#+ (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)+ )+ {-# INLINE min #-}+ max (NonTransitive.ProductOrd (FloatX2# a1 a2))+ (NonTransitive.ProductOrd (FloatX2# b1 b2))+ = NonTransitive.ProductOrd+ ( FloatX2#+ (if isTrue# (a1 `ltFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `ltFloat#` b2) then b2 else a2)+ )+ {-# INLINE max #-}++instance Ord (Partial.ProductOrd FloatX2) where+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (Partial.ProductOrd (FloatX2# a1 a2))+ (Partial.ProductOrd (FloatX2# b1 b2)) = isTrue#+ ((a1 `geFloat#` b1) `andI#` (a2 `geFloat#` b2))+ {-# INLINE (>=) #-}+ (<=) (Partial.ProductOrd (FloatX2# a1 a2))+ (Partial.ProductOrd (FloatX2# b1 b2)) = isTrue#+ ((a1 `leFloat#` b1) `andI#` (a2 `leFloat#` b2))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (Partial.ProductOrd (FloatX2# a1 a2))+ (Partial.ProductOrd (FloatX2# b1 b2))+ = Partial.ProductOrd+ ( FloatX2#+ (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)+ )+ {-# INLINE min #-}+ max (Partial.ProductOrd (FloatX2# a1 a2))+ (Partial.ProductOrd (FloatX2# b1 b2))+ = Partial.ProductOrd+ ( FloatX2#+ (if isTrue# (a1 `ltFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `ltFloat#` b2) then b2 else a2)+ )+ {-# INLINE max #-}++instance Ord FloatX2 where+ FloatX2# a1 a2 > FloatX2# b1 b2+ | isTrue# (a1 `gtFloat#` b1) = True+ | isTrue# (a1 `ltFloat#` b1) = False+ | isTrue# (a2 `gtFloat#` b2) = True+ | otherwise = False+ {-# INLINE (>) #-}++ FloatX2# a1 a2 < FloatX2# b1 b2+ | isTrue# (a1 `ltFloat#` b1) = True+ | isTrue# (a1 `gtFloat#` b1) = False+ | isTrue# (a2 `ltFloat#` b2) = True+ | otherwise = False+ {-# INLINE (<) #-}++ FloatX2# a1 a2 >= FloatX2# b1 b2+ | isTrue# (a1 `ltFloat#` b1) = False+ | isTrue# (a1 `gtFloat#` b1) = True+ | isTrue# (a2 `ltFloat#` b2) = False+ | otherwise = True+ {-# INLINE (>=) #-}++ FloatX2# a1 a2 <= FloatX2# b1 b2+ | isTrue# (a1 `gtFloat#` b1) = False+ | isTrue# (a1 `ltFloat#` b1) = True+ | isTrue# (a2 `gtFloat#` b2) = False+ | otherwise = True+ {-# INLINE (<=) #-}++ compare (FloatX2# a1 a2) (FloatX2# b1 b2)+ | isTrue# (a1 `gtFloat#` b1) = GT+ | isTrue# (a1 `ltFloat#` b1) = LT+ | isTrue# (a2 `gtFloat#` b2) = GT+ | isTrue# (a2 `ltFloat#` b2) = LT+ | otherwise = EQ+ {-# INLINE compare #-}++++-- | element-wise operations for vectors+instance Num FloatX2 where++ FloatX2# a1 a2 + FloatX2# b1 b2+ = FloatX2# (plusFloat# a1 b1) (plusFloat# a2 b2)+ {-# INLINE (+) #-}++ FloatX2# a1 a2 - FloatX2# b1 b2+ = FloatX2# (minusFloat# a1 b1) (minusFloat# a2 b2)+ {-# INLINE (-) #-}++ FloatX2# a1 a2 * FloatX2# b1 b2+ = FloatX2# (timesFloat# a1 b1) (timesFloat# a2 b2)+ {-# INLINE (*) #-}++ negate (FloatX2# a1 a2) = FloatX2#+ (negateFloat# a1) (negateFloat# a2)+ {-# INLINE negate #-}++ abs (FloatX2# a1 a2)+ = FloatX2#+ (if isTrue# (a1 `geFloat#` 0.0#) then a1 else negateFloat# a1)+ (if isTrue# (a2 `geFloat#` 0.0#) then a2 else negateFloat# a2)+ {-# INLINE abs #-}++ signum (FloatX2# a1 a2)+ = FloatX2# (if isTrue# (a1 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a1 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ (if isTrue# (a2 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a2 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ {-# INLINE signum #-}++ fromInteger n = case fromInteger n of F# x -> FloatX2# x x+ {-# INLINE fromInteger #-}++++instance Fractional FloatX2 where++ FloatX2# a1 a2 / FloatX2# b1 b2 = FloatX2#+ (divideFloat# a1 b1) (divideFloat# a2 b2)+ {-# INLINE (/) #-}++ recip (FloatX2# a1 a2) = FloatX2#+ (divideFloat# 1.0# a1) (divideFloat# 1.0# a2)+ {-# INLINE recip #-}++ fromRational r = case fromRational r of F# x -> FloatX2# x x+ {-# INLINE fromRational #-}++++instance Floating FloatX2 where++ pi = FloatX2#+ 3.141592653589793238#+ 3.141592653589793238#+ {-# INLINE pi #-}++ exp (FloatX2# a1 a2) = FloatX2#+ (expFloat# a1) (expFloat# a2)+ {-# INLINE exp #-}++ log (FloatX2# a1 a2) = FloatX2#+ (logFloat# a1) (logFloat# a2)+ {-# INLINE log #-}++ sqrt (FloatX2# a1 a2) = FloatX2#+ (sqrtFloat# a1) (sqrtFloat# a2)+ {-# INLINE sqrt #-}++ sin (FloatX2# a1 a2) = FloatX2#+ (sinFloat# a1) (sinFloat# a2)+ {-# INLINE sin #-}++ cos (FloatX2# a1 a2) = FloatX2#+ (cosFloat# a1) (cosFloat# a2)+ {-# INLINE cos #-}++ tan (FloatX2# a1 a2) = FloatX2#+ (tanFloat# a1) (tanFloat# a2)+ {-# INLINE tan #-}++ asin (FloatX2# a1 a2) = FloatX2#+ (asinFloat# a1) (asinFloat# a2)+ {-# INLINE asin #-}++ acos (FloatX2# a1 a2) = FloatX2#+ (acosFloat# a1) (acosFloat# a2)+ {-# INLINE acos #-}++ atan (FloatX2# a1 a2) = FloatX2#+ (atanFloat# a1) (atanFloat# a2)+ {-# INLINE atan #-}++ sinh (FloatX2# a1 a2) = FloatX2#+ (sinhFloat# a1) (sinhFloat# a2)+ {-# INLINE sinh #-}++ cosh (FloatX2# a1 a2) = FloatX2#+ (coshFloat# a1) (coshFloat# a2)+ {-# INLINE cosh #-}++ tanh (FloatX2# a1 a2) = FloatX2#+ (tanhFloat# a1) (tanhFloat# a2)+ {-# INLINE tanh #-}++ FloatX2# a1 a2 ** FloatX2# b1 b2 = FloatX2#+ (powerFloat# a1 b1) (powerFloat# a2 b2)+ {-# INLINE (**) #-}++ logBase x y = log y / log x+ {-# INLINE logBase #-}++ asinh x = log (x + sqrt (1.0+x*x))+ {-# INLINE asinh #-}++ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))+ {-# INLINE acosh #-}++ atanh x = 0.5 * log ((1.0+x) / (1.0-x))+ {-# INLINE atanh #-}++-- offset in bytes is S times bigger than offset in prim elements,+-- when S is power of two, this is equal to shift+#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 2#+#define ELEM_N 2++instance PrimBytes FloatX2 where++ getBytes (FloatX2# a1 a2) = case runRW#+ ( \s0 -> case newByteArray# (byteSize @FloatX2 undefined) s0 of+ (# s1, marr #) -> case writeFloatArray# marr 0# a1 s1 of+ s2 -> case writeFloatArray# marr 1# a2 s2 of+ s3 -> unsafeFreezeByteArray# marr s3+ ) of (# _, a #) -> a+ {-# INLINE getBytes #-}++ fromBytes off arr+ | i <- BOFF_TO_PRIMOFF(off)+ = FloatX2#+ (indexFloatArray# arr i)+ (indexFloatArray# arr (i +# 1#))+ {-# INLINE fromBytes #-}++ readBytes mba off s0+ | i <- BOFF_TO_PRIMOFF(off)+ = case readFloatArray# mba i s0 of+ (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> (# s2, FloatX2# a1 a2 #)+ {-# INLINE readBytes #-}++ writeBytes mba off (FloatX2# a1 a2) s+ | i <- BOFF_TO_PRIMOFF(off)+ = writeFloatArray# mba (i +# 1#) a2+ ( writeFloatArray# mba i a1 s )+ {-# INLINE writeBytes #-}++ readAddr addr s0+ = case readFloatOffAddr# addr 0# s0 of+ (# s1, a1 #) -> case readFloatOffAddr# addr 1# s1 of+ (# s2, a2 #) -> (# s2, FloatX2# a1 a2 #)+ {-# INLINE readAddr #-}++ writeAddr (FloatX2# a1 a2) addr s+ = writeFloatOffAddr# addr 1# a2+ ( writeFloatOffAddr# addr 0# a1 s )+ {-# INLINE writeAddr #-}++ byteSize _ = byteSize @Float undefined *# ELEM_N#+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign @Float undefined+ {-# INLINE byteAlign #-}++ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | i <- off *# ELEM_N#+ = FloatX2#+ (indexFloatArray# ba i)+ (indexFloatArray# ba (i +# 1#))+ {-# INLINE indexArray #-}++ readArray mba off s0+ | i <- off *# ELEM_N#+ = case readFloatArray# mba i s0 of+ (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> (# s2, FloatX2# a1 a2 #)+ {-# INLINE readArray #-}++ writeArray mba off (FloatX2# a1 a2) s+ | i <- off *# ELEM_N#+ = writeFloatArray# mba (i +# 1#) a2+ ( writeFloatArray# mba i a1 s )+ {-# INLINE writeArray #-}+++instance PrimArray Float FloatX2 where++ broadcast (F# x) = FloatX2# x x+ {-# INLINE broadcast #-}++ ix# 0# (FloatX2# a1 _) = F# a1+ ix# 1# (FloatX2# _ a2) = F# a2+ ix# _ _ = undefined+ {-# INLINE ix# #-}++ gen# _ f s0 = case f s0 of+ (# s1, F# a1 #) -> case f s1 of+ (# s2, F# a2 #) -> (# s2, FloatX2# a1 a2 #)+++ upd# _ 0# (F# q) (FloatX2# _ y) = FloatX2# q y+ upd# _ 1# (F# q) (FloatX2# x _) = FloatX2# x q+ upd# _ _ _ x = x+ {-# INLINE upd# #-}++ arrayContent# x = (# | (# CumulDims [ELEM_N, 1], 0#, getBytes x #) #)+ {-# INLINE arrayContent# #-}++ offsetElems _ = 0#+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims _ = Right (CumulDims [ELEM_N, 1])+ {-# INLINE uniqueOrCumulDims #-}++ fromElems _ off ba = FloatX2#+ (indexFloatArray# ba off)+ (indexFloatArray# ba (off +# 1#))+ {-# INLINE fromElems #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family/FloatX3.hs view
@@ -0,0 +1,437 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.DataFrame.Internal.Backend.Family.FloatX3 (FloatX3 (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+++data FloatX3 = FloatX3# Float# Float# Float#++-- | Since @Bounded@ is not implemented for floating point types, this instance+-- has an unresolvable constraint.+-- Nevetheless, it is good to have it here for nicer error messages.+instance Bounded Float => Bounded FloatX3 where+ maxBound = case maxBound of F# x -> FloatX3# x x x+ minBound = case minBound of F# x -> FloatX3# x x x+++instance Eq FloatX3 where++ FloatX3# a1 a2 a3 == FloatX3# b1 b2 b3 =+ isTrue#+ ( (a1 `eqFloat#` b1)+ `andI#` (a2 `eqFloat#` b2)+ `andI#` (a3 `eqFloat#` b3)+ )+ {-# INLINE (==) #-}++ FloatX3# a1 a2 a3 /= FloatX3# b1 b2 b3 =+ isTrue#+ ( (a1 `neFloat#` b1)+ `orI#` (a2 `neFloat#` b2)+ `orI#` (a3 `neFloat#` b3)+ )+ {-# INLINE (/=) #-}+++++cmp' :: Float# -> Float# -> PartialOrdering+cmp' a b+ | isTrue# (a `gtFloat#` b) = PGT+ | isTrue# (a `ltFloat#` b) = PLT+ | otherwise = PEQ++instance ProductOrder FloatX3 where+ cmp (FloatX3# a1 a2 a3) (FloatX3# b1 b2 b3)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ {-# INLINE cmp #-}++instance Ord (NonTransitive.ProductOrd FloatX3) where+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (NonTransitive.ProductOrd (FloatX3# a1 a2 a3))+ (NonTransitive.ProductOrd (FloatX3# b1 b2 b3)) = isTrue#+ ((a1 `geFloat#` b1) `andI#` (a2 `geFloat#` b2) `andI#` (a3 `geFloat#` b3))+ {-# INLINE (>=) #-}+ (<=) (NonTransitive.ProductOrd (FloatX3# a1 a2 a3))+ (NonTransitive.ProductOrd (FloatX3# b1 b2 b3)) = isTrue#+ ((a1 `leFloat#` b1) `andI#` (a2 `leFloat#` b2) `andI#` (a3 `leFloat#` b3))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (NonTransitive.ProductOrd (FloatX3# a1 a2 a3))+ (NonTransitive.ProductOrd (FloatX3# b1 b2 b3))+ = NonTransitive.ProductOrd+ ( FloatX3#+ (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `gtFloat#` b3) then b3 else a3)+ )+ {-# INLINE min #-}+ max (NonTransitive.ProductOrd (FloatX3# a1 a2 a3))+ (NonTransitive.ProductOrd (FloatX3# b1 b2 b3))+ = NonTransitive.ProductOrd+ ( FloatX3#+ (if isTrue# (a1 `ltFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `ltFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `ltFloat#` b3) then b3 else a3)+ )+ {-# INLINE max #-}++instance Ord (Partial.ProductOrd FloatX3) where+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (Partial.ProductOrd (FloatX3# a1 a2 a3))+ (Partial.ProductOrd (FloatX3# b1 b2 b3)) = isTrue#+ ((a1 `geFloat#` b1) `andI#` (a2 `geFloat#` b2) `andI#` (a3 `geFloat#` b3))+ {-# INLINE (>=) #-}+ (<=) (Partial.ProductOrd (FloatX3# a1 a2 a3))+ (Partial.ProductOrd (FloatX3# b1 b2 b3)) = isTrue#+ ((a1 `leFloat#` b1) `andI#` (a2 `leFloat#` b2) `andI#` (a3 `leFloat#` b3))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (Partial.ProductOrd (FloatX3# a1 a2 a3))+ (Partial.ProductOrd (FloatX3# b1 b2 b3))+ = Partial.ProductOrd+ ( FloatX3#+ (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `gtFloat#` b3) then b3 else a3)+ )+ {-# INLINE min #-}+ max (Partial.ProductOrd (FloatX3# a1 a2 a3))+ (Partial.ProductOrd (FloatX3# b1 b2 b3))+ = Partial.ProductOrd+ ( FloatX3#+ (if isTrue# (a1 `ltFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `ltFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `ltFloat#` b3) then b3 else a3)+ )+ {-# INLINE max #-}++instance Ord FloatX3 where+ FloatX3# a1 a2 a3 > FloatX3# b1 b2 b3+ | isTrue# (a1 `gtFloat#` b1) = True+ | isTrue# (a1 `ltFloat#` b1) = False+ | isTrue# (a2 `gtFloat#` b2) = True+ | isTrue# (a2 `ltFloat#` b2) = False+ | isTrue# (a3 `gtFloat#` b3) = True+ | otherwise = False+ {-# INLINE (>) #-}++ FloatX3# a1 a2 a3 < FloatX3# b1 b2 b3+ | isTrue# (a1 `ltFloat#` b1) = True+ | isTrue# (a1 `gtFloat#` b1) = False+ | isTrue# (a2 `ltFloat#` b2) = True+ | isTrue# (a2 `gtFloat#` b2) = False+ | isTrue# (a3 `ltFloat#` b3) = True+ | otherwise = False+ {-# INLINE (<) #-}++ FloatX3# a1 a2 a3 >= FloatX3# b1 b2 b3+ | isTrue# (a1 `ltFloat#` b1) = False+ | isTrue# (a1 `gtFloat#` b1) = True+ | isTrue# (a2 `ltFloat#` b2) = False+ | isTrue# (a2 `gtFloat#` b2) = True+ | isTrue# (a3 `ltFloat#` b3) = False+ | otherwise = True+ {-# INLINE (>=) #-}++ FloatX3# a1 a2 a3 <= FloatX3# b1 b2 b3+ | isTrue# (a1 `gtFloat#` b1) = False+ | isTrue# (a1 `ltFloat#` b1) = True+ | isTrue# (a2 `gtFloat#` b2) = False+ | isTrue# (a2 `ltFloat#` b2) = True+ | isTrue# (a3 `gtFloat#` b3) = False+ | otherwise = True+ {-# INLINE (<=) #-}++ compare (FloatX3# a1 a2 a3) (FloatX3# b1 b2 b3)+ | isTrue# (a1 `gtFloat#` b1) = GT+ | isTrue# (a1 `ltFloat#` b1) = LT+ | isTrue# (a2 `gtFloat#` b2) = GT+ | isTrue# (a2 `ltFloat#` b2) = LT+ | isTrue# (a3 `gtFloat#` b3) = GT+ | isTrue# (a3 `ltFloat#` b3) = LT+ | otherwise = EQ+ {-# INLINE compare #-}+++++-- | element-wise operations for vectors+instance Num FloatX3 where++ FloatX3# a1 a2 a3 + FloatX3# b1 b2 b3+ = FloatX3# (plusFloat# a1 b1) (plusFloat# a2 b2) (plusFloat# a3 b3)+ {-# INLINE (+) #-}++ FloatX3# a1 a2 a3 - FloatX3# b1 b2 b3+ = FloatX3# (minusFloat# a1 b1) (minusFloat# a2 b2) (minusFloat# a3 b3)+ {-# INLINE (-) #-}++ FloatX3# a1 a2 a3 * FloatX3# b1 b2 b3+ = FloatX3# (timesFloat# a1 b1) (timesFloat# a2 b2) (timesFloat# a3 b3)+ {-# INLINE (*) #-}++ negate (FloatX3# a1 a2 a3) = FloatX3#+ (negateFloat# a1) (negateFloat# a2) (negateFloat# a3)+ {-# INLINE negate #-}++ abs (FloatX3# a1 a2 a3)+ = FloatX3#+ (if isTrue# (a1 `geFloat#` 0.0#) then a1 else negateFloat# a1)+ (if isTrue# (a2 `geFloat#` 0.0#) then a2 else negateFloat# a2)+ (if isTrue# (a3 `geFloat#` 0.0#) then a3 else negateFloat# a3)+ {-# INLINE abs #-}++ signum (FloatX3# a1 a2 a3)+ = FloatX3# (if isTrue# (a1 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a1 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ (if isTrue# (a2 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a2 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ (if isTrue# (a3 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a3 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ {-# INLINE signum #-}++ fromInteger n = case fromInteger n of F# x -> FloatX3# x x x+ {-# INLINE fromInteger #-}++++instance Fractional FloatX3 where++ FloatX3# a1 a2 a3 / FloatX3# b1 b2 b3 = FloatX3#+ (divideFloat# a1 b1) (divideFloat# a2 b2) (divideFloat# a3 b3)+ {-# INLINE (/) #-}++ recip (FloatX3# a1 a2 a3) = FloatX3#+ (divideFloat# 1.0# a1) (divideFloat# 1.0# a2) (divideFloat# 1.0# a3)+ {-# INLINE recip #-}++ fromRational r = case fromRational r of F# x -> FloatX3# x x x+ {-# INLINE fromRational #-}++++instance Floating FloatX3 where++ pi = FloatX3#+ 3.141592653589793238#+ 3.141592653589793238#+ 3.141592653589793238#+ {-# INLINE pi #-}++ exp (FloatX3# a1 a2 a3) = FloatX3#+ (expFloat# a1) (expFloat# a2) (expFloat# a3)+ {-# INLINE exp #-}++ log (FloatX3# a1 a2 a3) = FloatX3#+ (logFloat# a1) (logFloat# a2) (logFloat# a3)+ {-# INLINE log #-}++ sqrt (FloatX3# a1 a2 a3) = FloatX3#+ (sqrtFloat# a1) (sqrtFloat# a2) (sqrtFloat# a3)+ {-# INLINE sqrt #-}++ sin (FloatX3# a1 a2 a3) = FloatX3#+ (sinFloat# a1) (sinFloat# a2) (sinFloat# a3)+ {-# INLINE sin #-}++ cos (FloatX3# a1 a2 a3) = FloatX3#+ (cosFloat# a1) (cosFloat# a2) (cosFloat# a3)+ {-# INLINE cos #-}++ tan (FloatX3# a1 a2 a3) = FloatX3#+ (tanFloat# a1) (tanFloat# a2) (tanFloat# a3)+ {-# INLINE tan #-}++ asin (FloatX3# a1 a2 a3) = FloatX3#+ (asinFloat# a1) (asinFloat# a2) (asinFloat# a3)+ {-# INLINE asin #-}++ acos (FloatX3# a1 a2 a3) = FloatX3#+ (acosFloat# a1) (acosFloat# a2) (acosFloat# a3)+ {-# INLINE acos #-}++ atan (FloatX3# a1 a2 a3) = FloatX3#+ (atanFloat# a1) (atanFloat# a2) (atanFloat# a3)+ {-# INLINE atan #-}++ sinh (FloatX3# a1 a2 a3) = FloatX3#+ (sinhFloat# a1) (sinhFloat# a2) (sinhFloat# a3)+ {-# INLINE sinh #-}++ cosh (FloatX3# a1 a2 a3) = FloatX3#+ (coshFloat# a1) (coshFloat# a2) (coshFloat# a3)+ {-# INLINE cosh #-}++ tanh (FloatX3# a1 a2 a3) = FloatX3#+ (tanhFloat# a1) (tanhFloat# a2) (tanhFloat# a3)+ {-# INLINE tanh #-}++ FloatX3# a1 a2 a3 ** FloatX3# b1 b2 b3 = FloatX3#+ (powerFloat# a1 b1) (powerFloat# a2 b2) (powerFloat# a3 b3)+ {-# INLINE (**) #-}++ logBase x y = log y / log x+ {-# INLINE logBase #-}++ asinh x = log (x + sqrt (1.0+x*x))+ {-# INLINE asinh #-}++ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))+ {-# INLINE acosh #-}++ atanh x = 0.5 * log ((1.0+x) / (1.0-x))+ {-# INLINE atanh #-}++-- offset in bytes is S times bigger than offset in prim elements,+-- when S is power of two, this is equal to shift+#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 2#+#define ELEM_N 3++instance PrimBytes FloatX3 where++ getBytes (FloatX3# a1 a2 a3) = case runRW#+ ( \s0 -> case newByteArray# (byteSize @FloatX3 undefined) s0 of+ (# s1, marr #) -> case writeFloatArray# marr 0# a1 s1 of+ s2 -> case writeFloatArray# marr 1# a2 s2 of+ s3 -> case writeFloatArray# marr 2# a3 s3 of+ s4 -> unsafeFreezeByteArray# marr s4+ ) of (# _, a #) -> a+ {-# INLINE getBytes #-}++ fromBytes off arr+ | i <- BOFF_TO_PRIMOFF(off)+ = FloatX3#+ (indexFloatArray# arr i)+ (indexFloatArray# arr (i +# 1#))+ (indexFloatArray# arr (i +# 2#))+ {-# INLINE fromBytes #-}++ readBytes mba off s0+ | i <- BOFF_TO_PRIMOFF(off)+ = case readFloatArray# mba i s0 of+ (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> (# s3, FloatX3# a1 a2 a3 #)+ {-# INLINE readBytes #-}++ writeBytes mba off (FloatX3# a1 a2 a3) s+ | i <- BOFF_TO_PRIMOFF(off)+ = writeFloatArray# mba (i +# 2#) a3+ ( writeFloatArray# mba (i +# 1#) a2+ ( writeFloatArray# mba i a1 s ))+ {-# INLINE writeBytes #-}++ readAddr addr s0+ = case readFloatOffAddr# addr 0# s0 of+ (# s1, a1 #) -> case readFloatOffAddr# addr 1# s1 of+ (# s2, a2 #) -> case readFloatOffAddr# addr 2# s2 of+ (# s3, a3 #) -> (# s3, FloatX3# a1 a2 a3 #)+ {-# INLINE readAddr #-}++ writeAddr (FloatX3# a1 a2 a3) addr s+ = writeFloatOffAddr# addr 2# a3+ ( writeFloatOffAddr# addr 1# a2+ ( writeFloatOffAddr# addr 0# a1 s ))+ {-# INLINE writeAddr #-}++ byteSize _ = byteSize @Float undefined *# ELEM_N#+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign @Float undefined+ {-# INLINE byteAlign #-}++ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | i <- off *# ELEM_N#+ = FloatX3#+ (indexFloatArray# ba i)+ (indexFloatArray# ba (i +# 1#))+ (indexFloatArray# ba (i +# 2#))+ {-# INLINE indexArray #-}++ readArray mba off s0+ | i <- off *# ELEM_N#+ = case readFloatArray# mba i s0 of+ (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> (# s3, FloatX3# a1 a2 a3 #)+ {-# INLINE readArray #-}++ writeArray mba off (FloatX3# a1 a2 a3) s+ | i <- off *# ELEM_N#+ = writeFloatArray# mba (i +# 2#) a3+ ( writeFloatArray# mba (i +# 1#) a2+ ( writeFloatArray# mba i a1 s ))+ {-# INLINE writeArray #-}+++instance PrimArray Float FloatX3 where++ broadcast (F# x) = FloatX3# x x x+ {-# INLINE broadcast #-}++ ix# 0# (FloatX3# a1 _ _) = F# a1+ ix# 1# (FloatX3# _ a2 _) = F# a2+ ix# 2# (FloatX3# _ _ a3) = F# a3+ ix# _ _ = undefined+ {-# INLINE ix# #-}++ gen# _ f s0 = case f s0 of+ (# s1, F# a1 #) -> case f s1 of+ (# s2, F# a2 #) -> case f s2 of+ (# s3, F# a3 #) -> (# s3, FloatX3# a1 a2 a3 #)+++ upd# _ 0# (F# q) (FloatX3# _ y z) = FloatX3# q y z+ upd# _ 1# (F# q) (FloatX3# x _ z) = FloatX3# x q z+ upd# _ 2# (F# q) (FloatX3# x y _) = FloatX3# x y q+ upd# _ _ _ x = x+ {-# INLINE upd# #-}++ arrayContent# x = (# | (# CumulDims [ELEM_N, 1], 0#, getBytes x #) #)+ {-# INLINE arrayContent# #-}++ offsetElems _ = 0#+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims _ = Right (CumulDims [ELEM_N, 1])+ {-# INLINE uniqueOrCumulDims #-}++ fromElems _ off ba = FloatX3#+ (indexFloatArray# ba off)+ (indexFloatArray# ba (off +# 1#))+ (indexFloatArray# ba (off +# 2#))+ {-# INLINE fromElems #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family/FloatX4.hs view
@@ -0,0 +1,498 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Numeric.DataFrame.Internal.Backend.Family.FloatX4 (FloatX4 (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.SubSpace+import Numeric.Dimensions+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+++data FloatX4 = FloatX4# Float# Float# Float# Float#++-- | Since @Bounded@ is not implemented for floating point types, this instance+-- has an unresolvable constraint.+-- Nevetheless, it is good to have it here for nicer error messages.+instance Bounded Float => Bounded FloatX4 where+ maxBound = case maxBound of F# x -> FloatX4# x x x x+ minBound = case minBound of F# x -> FloatX4# x x x x+++instance Eq FloatX4 where++ FloatX4# a1 a2 a3 a4 == FloatX4# b1 b2 b3 b4 =+ isTrue#+ ( (a1 `eqFloat#` b1)+ `andI#` (a2 `eqFloat#` b2)+ `andI#` (a3 `eqFloat#` b3)+ `andI#` (a4 `eqFloat#` b4)+ )+ {-# INLINE (==) #-}++ FloatX4# a1 a2 a3 a4 /= FloatX4# b1 b2 b3 b4 =+ isTrue#+ ( (a1 `neFloat#` b1)+ `orI#` (a2 `neFloat#` b2)+ `orI#` (a3 `neFloat#` b3)+ `orI#` (a4 `neFloat#` b4)+ )+ {-# INLINE (/=) #-}+++++cmp' :: Float# -> Float# -> PartialOrdering+cmp' a b+ | isTrue# (a `gtFloat#` b) = PGT+ | isTrue# (a `ltFloat#` b) = PLT+ | otherwise = PEQ++instance ProductOrder FloatX4 where+ cmp (FloatX4# a1 a2 a3 a4) (FloatX4# b1 b2 b3 b4)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3 <> cmp' a4 b4+ {-# INLINE cmp #-}++instance Ord (NonTransitive.ProductOrd FloatX4) where+ NonTransitive.ProductOrd x > NonTransitive.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ NonTransitive.ProductOrd x < NonTransitive.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (NonTransitive.ProductOrd (FloatX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (FloatX4# b1 b2 b3 b4)) = isTrue#+ ((a1 `geFloat#` b1) `andI#` (a2 `geFloat#` b2) `andI#` (a3 `geFloat#` b3) `andI#` (a4 `geFloat#` b4))+ {-# INLINE (>=) #-}+ (<=) (NonTransitive.ProductOrd (FloatX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (FloatX4# b1 b2 b3 b4)) = isTrue#+ ((a1 `leFloat#` b1) `andI#` (a2 `leFloat#` b2) `andI#` (a3 `leFloat#` b3) `andI#` (a4 `leFloat#` b4))+ {-# INLINE (<=) #-}+ compare (NonTransitive.ProductOrd a) (NonTransitive.ProductOrd b)+ = NonTransitive.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (NonTransitive.ProductOrd (FloatX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (FloatX4# b1 b2 b3 b4))+ = NonTransitive.ProductOrd+ ( FloatX4#+ (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `gtFloat#` b3) then b3 else a3)+ (if isTrue# (a4 `gtFloat#` b4) then b4 else a4)+ )+ {-# INLINE min #-}+ max (NonTransitive.ProductOrd (FloatX4# a1 a2 a3 a4))+ (NonTransitive.ProductOrd (FloatX4# b1 b2 b3 b4))+ = NonTransitive.ProductOrd+ ( FloatX4#+ (if isTrue# (a1 `ltFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `ltFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `ltFloat#` b3) then b3 else a3)+ (if isTrue# (a4 `ltFloat#` b4) then b4 else a4)+ )+ {-# INLINE max #-}++instance Ord (Partial.ProductOrd FloatX4) where+ Partial.ProductOrd x > Partial.ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ Partial.ProductOrd x < Partial.ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ (>=) (Partial.ProductOrd (FloatX4# a1 a2 a3 a4))+ (Partial.ProductOrd (FloatX4# b1 b2 b3 b4)) = isTrue#+ ((a1 `geFloat#` b1) `andI#` (a2 `geFloat#` b2) `andI#` (a3 `geFloat#` b3) `andI#` (a4 `geFloat#` b4))+ {-# INLINE (>=) #-}+ (<=) (Partial.ProductOrd (FloatX4# a1 a2 a3 a4))+ (Partial.ProductOrd (FloatX4# b1 b2 b3 b4)) = isTrue#+ ((a1 `leFloat#` b1) `andI#` (a2 `leFloat#` b2) `andI#` (a3 `leFloat#` b3) `andI#` (a4 `leFloat#` b4))+ {-# INLINE (<=) #-}+ compare (Partial.ProductOrd a) (Partial.ProductOrd b)+ = Partial.toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (Partial.ProductOrd (FloatX4# a1 a2 a3 a4))+ (Partial.ProductOrd (FloatX4# b1 b2 b3 b4))+ = Partial.ProductOrd+ ( FloatX4#+ (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `gtFloat#` b3) then b3 else a3)+ (if isTrue# (a4 `gtFloat#` b4) then b4 else a4)+ )+ {-# INLINE min #-}+ max (Partial.ProductOrd (FloatX4# a1 a2 a3 a4))+ (Partial.ProductOrd (FloatX4# b1 b2 b3 b4))+ = Partial.ProductOrd+ ( FloatX4#+ (if isTrue# (a1 `ltFloat#` b1) then b1 else a1)+ (if isTrue# (a2 `ltFloat#` b2) then b2 else a2)+ (if isTrue# (a3 `ltFloat#` b3) then b3 else a3)+ (if isTrue# (a4 `ltFloat#` b4) then b4 else a4)+ )+ {-# INLINE max #-}++instance Ord FloatX4 where+ FloatX4# a1 a2 a3 a4 > FloatX4# b1 b2 b3 b4+ | isTrue# (a1 `gtFloat#` b1) = True+ | isTrue# (a1 `ltFloat#` b1) = False+ | isTrue# (a2 `gtFloat#` b2) = True+ | isTrue# (a2 `ltFloat#` b2) = False+ | isTrue# (a3 `gtFloat#` b3) = True+ | isTrue# (a3 `ltFloat#` b3) = False+ | isTrue# (a4 `gtFloat#` b4) = True+ | otherwise = False+ {-# INLINE (>) #-}++ FloatX4# a1 a2 a3 a4 < FloatX4# b1 b2 b3 b4+ | isTrue# (a1 `ltFloat#` b1) = True+ | isTrue# (a1 `gtFloat#` b1) = False+ | isTrue# (a2 `ltFloat#` b2) = True+ | isTrue# (a2 `gtFloat#` b2) = False+ | isTrue# (a3 `ltFloat#` b3) = True+ | isTrue# (a3 `gtFloat#` b3) = False+ | isTrue# (a4 `ltFloat#` b4) = True+ | otherwise = False+ {-# INLINE (<) #-}++ FloatX4# a1 a2 a3 a4 >= FloatX4# b1 b2 b3 b4+ | isTrue# (a1 `ltFloat#` b1) = False+ | isTrue# (a1 `gtFloat#` b1) = True+ | isTrue# (a2 `ltFloat#` b2) = False+ | isTrue# (a2 `gtFloat#` b2) = True+ | isTrue# (a3 `ltFloat#` b3) = False+ | isTrue# (a3 `gtFloat#` b3) = True+ | isTrue# (a4 `ltFloat#` b4) = False+ | otherwise = True+ {-# INLINE (>=) #-}++ FloatX4# a1 a2 a3 a4 <= FloatX4# b1 b2 b3 b4+ | isTrue# (a1 `gtFloat#` b1) = False+ | isTrue# (a1 `ltFloat#` b1) = True+ | isTrue# (a2 `gtFloat#` b2) = False+ | isTrue# (a2 `ltFloat#` b2) = True+ | isTrue# (a3 `gtFloat#` b3) = False+ | isTrue# (a3 `ltFloat#` b3) = True+ | isTrue# (a4 `gtFloat#` b4) = False+ | otherwise = True+ {-# INLINE (<=) #-}++ compare (FloatX4# a1 a2 a3 a4) (FloatX4# b1 b2 b3 b4)+ | isTrue# (a1 `gtFloat#` b1) = GT+ | isTrue# (a1 `ltFloat#` b1) = LT+ | isTrue# (a2 `gtFloat#` b2) = GT+ | isTrue# (a2 `ltFloat#` b2) = LT+ | isTrue# (a3 `gtFloat#` b3) = GT+ | isTrue# (a3 `ltFloat#` b3) = LT+ | isTrue# (a4 `gtFloat#` b4) = GT+ | isTrue# (a4 `ltFloat#` b4) = LT+ | otherwise = EQ+ {-# INLINE compare #-}+++-- | element-wise operations for vectors+instance Num FloatX4 where++ FloatX4# a1 a2 a3 a4 + FloatX4# b1 b2 b3 b4+ = FloatX4# (plusFloat# a1 b1) (plusFloat# a2 b2) (plusFloat# a3 b3) (plusFloat# a4 b4)+ {-# INLINE (+) #-}++ FloatX4# a1 a2 a3 a4 - FloatX4# b1 b2 b3 b4+ = FloatX4# (minusFloat# a1 b1) (minusFloat# a2 b2) (minusFloat# a3 b3) (minusFloat# a4 b4)+ {-# INLINE (-) #-}++ FloatX4# a1 a2 a3 a4 * FloatX4# b1 b2 b3 b4+ = FloatX4# (timesFloat# a1 b1) (timesFloat# a2 b2) (timesFloat# a3 b3) (timesFloat# a4 b4)+ {-# INLINE (*) #-}++ negate (FloatX4# a1 a2 a3 a4) = FloatX4#+ (negateFloat# a1) (negateFloat# a2) (negateFloat# a3) (negateFloat# a4)+ {-# INLINE negate #-}++ abs (FloatX4# a1 a2 a3 a4)+ = FloatX4#+ (if isTrue# (a1 `geFloat#` 0.0#) then a1 else negateFloat# a1)+ (if isTrue# (a2 `geFloat#` 0.0#) then a2 else negateFloat# a2)+ (if isTrue# (a3 `geFloat#` 0.0#) then a3 else negateFloat# a3)+ (if isTrue# (a4 `geFloat#` 0.0#) then a4 else negateFloat# a4)+ {-# INLINE abs #-}++ signum (FloatX4# a1 a2 a3 a4)+ = FloatX4# (if isTrue# (a1 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a1 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ (if isTrue# (a2 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a2 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ (if isTrue# (a3 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a3 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ (if isTrue# (a4 `gtFloat#` 0.0#)+ then 1.0#+ else if isTrue# (a4 `ltFloat#` 0.0#) then -1.0# else 0.0# )+ {-# INLINE signum #-}++ fromInteger n = case fromInteger n of F# x -> FloatX4# x x x x+ {-# INLINE fromInteger #-}++++instance Fractional FloatX4 where++ FloatX4# a1 a2 a3 a4 / FloatX4# b1 b2 b3 b4 = FloatX4#+ (divideFloat# a1 b1) (divideFloat# a2 b2) (divideFloat# a3 b3) (divideFloat# a4 b4)+ {-# INLINE (/) #-}++ recip (FloatX4# a1 a2 a3 a4) = FloatX4#+ (divideFloat# 1.0# a1) (divideFloat# 1.0# a2) (divideFloat# 1.0# a3) (divideFloat# 1.0# a4)+ {-# INLINE recip #-}++ fromRational r = case fromRational r of F# x -> FloatX4# x x x x+ {-# INLINE fromRational #-}++++instance Floating FloatX4 where++ pi = FloatX4#+ 3.141592653589793238#+ 3.141592653589793238#+ 3.141592653589793238#+ 3.141592653589793238#+ {-# INLINE pi #-}++ exp (FloatX4# a1 a2 a3 a4) = FloatX4#+ (expFloat# a1) (expFloat# a2) (expFloat# a3) (expFloat# a4)+ {-# INLINE exp #-}++ log (FloatX4# a1 a2 a3 a4) = FloatX4#+ (logFloat# a1) (logFloat# a2) (logFloat# a3) (logFloat# a4)+ {-# INLINE log #-}++ sqrt (FloatX4# a1 a2 a3 a4) = FloatX4#+ (sqrtFloat# a1) (sqrtFloat# a2) (sqrtFloat# a3) (sqrtFloat# a4)+ {-# INLINE sqrt #-}++ sin (FloatX4# a1 a2 a3 a4) = FloatX4#+ (sinFloat# a1) (sinFloat# a2) (sinFloat# a3) (sinFloat# a4)+ {-# INLINE sin #-}++ cos (FloatX4# a1 a2 a3 a4) = FloatX4#+ (cosFloat# a1) (cosFloat# a2) (cosFloat# a3) (cosFloat# a4)+ {-# INLINE cos #-}++ tan (FloatX4# a1 a2 a3 a4) = FloatX4#+ (tanFloat# a1) (tanFloat# a2) (tanFloat# a3) (tanFloat# a4)+ {-# INLINE tan #-}++ asin (FloatX4# a1 a2 a3 a4) = FloatX4#+ (asinFloat# a1) (asinFloat# a2) (asinFloat# a3) (asinFloat# a4)+ {-# INLINE asin #-}++ acos (FloatX4# a1 a2 a3 a4) = FloatX4#+ (acosFloat# a1) (acosFloat# a2) (acosFloat# a3) (acosFloat# a4)+ {-# INLINE acos #-}++ atan (FloatX4# a1 a2 a3 a4) = FloatX4#+ (atanFloat# a1) (atanFloat# a2) (atanFloat# a3) (atanFloat# a4)+ {-# INLINE atan #-}++ sinh (FloatX4# a1 a2 a3 a4) = FloatX4#+ (sinhFloat# a1) (sinhFloat# a2) (sinhFloat# a3) (sinhFloat# a4)+ {-# INLINE sinh #-}++ cosh (FloatX4# a1 a2 a3 a4) = FloatX4#+ (coshFloat# a1) (coshFloat# a2) (coshFloat# a3) (coshFloat# a4)+ {-# INLINE cosh #-}++ tanh (FloatX4# a1 a2 a3 a4) = FloatX4#+ (tanhFloat# a1) (tanhFloat# a2) (tanhFloat# a3) (tanhFloat# a4)+ {-# INLINE tanh #-}++ FloatX4# a1 a2 a3 a4 ** FloatX4# b1 b2 b3 b4 = FloatX4#+ (powerFloat# a1 b1) (powerFloat# a2 b2) (powerFloat# a3 b3) (powerFloat# a4 b4)+ {-# INLINE (**) #-}++ logBase x y = log y / log x+ {-# INLINE logBase #-}++ asinh x = log (x + sqrt (1.0+x*x))+ {-# INLINE asinh #-}++ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))+ {-# INLINE acosh #-}++ atanh x = 0.5 * log ((1.0+x) / (1.0-x))+ {-# INLINE atanh #-}++-- offset in bytes is S times bigger than offset in prim elements,+-- when S is power of two, this is equal to shift+#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 2#+#define ELEM_N 4++instance PrimBytes FloatX4 where++ getBytes (FloatX4# a1 a2 a3 a4) = case runRW#+ ( \s0 -> case newByteArray# (byteSize @FloatX4 undefined) s0 of+ (# s1, marr #) -> case writeFloatArray# marr 0# a1 s1 of+ s2 -> case writeFloatArray# marr 1# a2 s2 of+ s3 -> case writeFloatArray# marr 2# a3 s3 of+ s4 -> case writeFloatArray# marr 3# a4 s4 of+ s5 -> unsafeFreezeByteArray# marr s5+ ) of (# _, a #) -> a+ {-# INLINE getBytes #-}++ fromBytes off arr+ | i <- BOFF_TO_PRIMOFF(off)+ = FloatX4#+ (indexFloatArray# arr i)+ (indexFloatArray# arr (i +# 1#))+ (indexFloatArray# arr (i +# 2#))+ (indexFloatArray# arr (i +# 3#))+ {-# INLINE fromBytes #-}++ readBytes mba off s0+ | i <- BOFF_TO_PRIMOFF(off)+ = case readFloatArray# mba i s0 of+ (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> case readFloatArray# mba (i +# 3#) s3 of+ (# s4, a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)+ {-# INLINE readBytes #-}++ writeBytes mba off (FloatX4# a1 a2 a3 a4) s+ | i <- BOFF_TO_PRIMOFF(off)+ = writeFloatArray# mba (i +# 3#) a4+ ( writeFloatArray# mba (i +# 2#) a3+ ( writeFloatArray# mba (i +# 1#) a2+ ( writeFloatArray# mba i a1 s )))+ {-# INLINE writeBytes #-}++ readAddr addr s0+ = case readFloatOffAddr# addr 0# s0 of+ (# s1, a1 #) -> case readFloatOffAddr# addr 1# s1 of+ (# s2, a2 #) -> case readFloatOffAddr# addr 2# s2 of+ (# s3, a3 #) -> case readFloatOffAddr# addr 3# s3 of+ (# s4, a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)+ {-# INLINE readAddr #-}++ writeAddr (FloatX4# a1 a2 a3 a4) addr s+ = writeFloatOffAddr# addr 3# a4+ ( writeFloatOffAddr# addr 2# a3+ ( writeFloatOffAddr# addr 1# a2+ ( writeFloatOffAddr# addr 0# a1 s )))+ {-# INLINE writeAddr #-}++ byteSize _ = byteSize @Float undefined *# ELEM_N#+ {-# INLINE byteSize #-}++ byteAlign _ = byteAlign @Float undefined+ {-# INLINE byteAlign #-}++ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}++ indexArray ba off+ | i <- off *# ELEM_N#+ = FloatX4#+ (indexFloatArray# ba i)+ (indexFloatArray# ba (i +# 1#))+ (indexFloatArray# ba (i +# 2#))+ (indexFloatArray# ba (i +# 3#))+ {-# INLINE indexArray #-}++ readArray mba off s0+ | i <- off *# ELEM_N#+ = case readFloatArray# mba i s0 of+ (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of+ (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of+ (# s3, a3 #) -> case readFloatArray# mba (i +# 3#) s3 of+ (# s4, a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)+ {-# INLINE readArray #-}++ writeArray mba off (FloatX4# a1 a2 a3 a4) s+ | i <- off *# ELEM_N#+ = writeFloatArray# mba (i +# 3#) a4+ ( writeFloatArray# mba (i +# 2#) a3+ ( writeFloatArray# mba (i +# 1#) a2+ ( writeFloatArray# mba i a1 s )))+ {-# INLINE writeArray #-}+++instance PrimArray Float FloatX4 where++ broadcast (F# x) = FloatX4# x x x x+ {-# INLINE broadcast #-}++ ix# 0# (FloatX4# a1 _ _ _) = F# a1+ ix# 1# (FloatX4# _ a2 _ _) = F# a2+ ix# 2# (FloatX4# _ _ a3 _) = F# a3+ ix# 3# (FloatX4# _ _ _ a4) = F# a4+ ix# _ _ = undefined+ {-# INLINE ix# #-}++ gen# _ f s0 = case f s0 of+ (# s1, F# a1 #) -> case f s1 of+ (# s2, F# a2 #) -> case f s2 of+ (# s3, F# a3 #) -> case f s3 of+ (# s4, F# a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)+++ upd# _ 0# (F# q) (FloatX4# _ y z w) = FloatX4# q y z w+ upd# _ 1# (F# q) (FloatX4# x _ z w) = FloatX4# x q z w+ upd# _ 2# (F# q) (FloatX4# x y _ w) = FloatX4# x y q w+ upd# _ 3# (F# q) (FloatX4# x y z _) = FloatX4# x y z q+ upd# _ _ _ x = x+ {-# INLINE upd# #-}++ arrayContent# x = (# | (# CumulDims [ELEM_N, 1], 0#, getBytes x #) #)+ {-# INLINE arrayContent# #-}++ offsetElems _ = 0#+ {-# INLINE offsetElems #-}++ uniqueOrCumulDims _ = Right (CumulDims [ELEM_N, 1])+ {-# INLINE uniqueOrCumulDims #-}++ fromElems _ off ba = FloatX4#+ (indexFloatArray# ba off)+ (indexFloatArray# ba (off +# 1#))+ (indexFloatArray# ba (off +# 2#))+ (indexFloatArray# ba (off +# 3#))+ {-# INLINE fromElems #-}+++--------------------------------------------------------------------------------+-- Rewrite rules to improve efficiency of algorithms+--+-- Here we don't have access to DataFrame constructors, because we cannot import+-- Numeric.DataFrame.Type module.+-- However, we know that all DataFrame instances are just newtype wrappers+-- (as well as Scalar). Thus, we can use unsafeCoerce# to get access to Arrays+-- inside DataFrames.+--+--------------------------------------------------------------------------------++getIdxOffset :: Idxs '[4] -> Int#+getIdxOffset is = case unsafeCoerce# is of+ [W# i] -> word2Int# i+ _ -> 0#+{-# INLINE getIdxOffset #-}+++{-# RULES+"index/FloatX4" forall i . index @Float @'[4] i+ = unsafeCoerce# (ix# @Float @FloatX4 (getIdxOffset i))++ #-}
+ src-base/Numeric/DataFrame/Internal/Backend/Family/ScalarBase.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE UnboxedSums #-}+{-# LANGUAGE UnboxedTuples #-}+module Numeric.DataFrame.Internal.Backend.Family.ScalarBase (ScalarBase (..)) where+++import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial++-- | Specialize ScalarBase type without any arrays+newtype ScalarBase t = ScalarBase { _unScalarBase :: t }+ deriving ( Enum, Eq, Bounded, Integral+ , Num, Fractional, Floating, Ord, Real, RealFrac, RealFloat+ , PrimBytes)++instance Ord t => ProductOrder (ScalarBase t) where+ cmp a b = fromOrdering (compare (_unScalarBase a) (_unScalarBase b))+deriving instance Ord t => Ord (NonTransitive.ProductOrd (ScalarBase t))+deriving instance Ord t => Ord (Partial.ProductOrd (ScalarBase t))++instance PrimBytes t => PrimArray t (ScalarBase t) where+ broadcast = unsafeCoerce#+ {-# INLINE broadcast #-}+ ix# _ = unsafeCoerce#+ {-# INLINE ix# #-}+ gen# _ = unsafeCoerce#+ {-# INLINE gen# #-}+ upd# _ 0# = const . ScalarBase+ upd# _ _ = const id+ {-# INLINE upd# #-}+ arrayContent# x = (# _unScalarBase x | #)+ {-# INLINE arrayContent# #-}+ offsetElems _ = 0#+ {-# INLINE offsetElems #-}+ uniqueOrCumulDims = Left . _unScalarBase+ {-# INLINE uniqueOrCumulDims #-}+ fromElems _ off ba = indexArray ba off+ {-# INLINE fromElems #-}++_suppressHlintUnboxedTuplesWarning :: () -> (# (), () #)+_suppressHlintUnboxedTuplesWarning = undefined
src/Numeric/DataFrame.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE PatternSynonyms #-}- module Numeric.DataFrame ( module Numeric.DataFrame.Type -- * Simplified type aliases@@ -9,16 +7,14 @@ -- * Functionality , module Numeric.DataFrame.SubSpace , module Numeric.DataFrame.Contraction- , module Numeric.DataFrame.Shape ) where -import Numeric.DataFrame.Internal.Array ()+import Numeric.DataFrame.Internal.Backend () -import Numeric.DataFrame.Contraction-import Numeric.DataFrame.Shape-import Numeric.DataFrame.SubSpace-import Numeric.DataFrame.Type+import Numeric.DataFrame.Contraction+import Numeric.DataFrame.SubSpace+import Numeric.DataFrame.Type -import Numeric.Matrix-import Numeric.Scalar-import Numeric.Vector+import Numeric.Matrix+import Numeric.Scalar+import Numeric.Vector
src/Numeric/DataFrame/Contraction.hs view
@@ -30,11 +30,11 @@ ( Contraction (..), (%*) ) where -import GHC.Base+import GHC.Base -import Numeric.DataFrame.Family-import Numeric.DataFrame.Internal.Array.Class-import Numeric.Dimensions+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.Type+import Numeric.Dimensions @@ -55,13 +55,12 @@ -- 1. matrix-matrix product -- 2. matrix-vector or vector-matrix product -- 3. dot product of two vectors.-(%*) :: ( ConcatList as bs (as ++ bs)- , Contraction t as bs asbs+(%*) :: ( Contraction t as bs asbs , KnownDim m , PrimArray t (DataFrame t (as +: m)) , PrimArray t (DataFrame t (m :+ bs))- , PrimArray t (DataFrame t (as ++ bs))- ) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t (as ++ bs)+ , PrimArray t (DataFrame t asbs)+ ) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t asbs (%*) = contract {-# INLINE (%*) #-} infixl 7 %*@@ -73,6 +72,7 @@ , Dimensions bs , Num t ) => Contraction t as bs asbs where+ contract :: forall m . ( KnownDim m , PrimArray t (DataFrame t (as +: m))@@ -80,19 +80,40 @@ , PrimArray t (DataFrame t asbs) ) => DataFrame t (as +: m) -> DataFrame t (m :+ bs) -> DataFrame t asbs- contract x y- | I# m <- fromIntegral $ dimVal' @m- , I# n <- fromIntegral $ totalDim' @as- , I# k <- fromIntegral $ totalDim' @bs- , nk <- n *# k- = let loop i j l r | isTrue# (l ==# m) = r+ contract x y = case (# uniqueOrCumulDims x, uniqueOrCumulDims y #) of+ (# Left x0, Left y0 #) -> broadcast (x0 * y0)+ (# ux, uy #)+ | dm <- dim @m+ , (ixX, xs) <- getStepsAndIx (Snoc dims dm) x ux+ , (ixY, ys) <- getStepsAndIx (Cons dm dims) y uy+ , (# n, m, k, steps #) <- conSteps xs ys ->+ let loop i j l r | isTrue# (l ==# m) = r | otherwise = loop i j (l +# 1#)- (r + ix# (i +# n *# l) x * ix# (l +# m *# j) y)+ (r + ixX (i *# m +# l) * ixY (l *# k +# j)) - loop2 (T# i j) | isTrue# (j ==# k) = (# T# i j, 0 #)- | isTrue# (i ==# n) = loop2 (T# 0# (j +# 1#))- | otherwise = (# T# (i +# 1#) j, loop i j 0# 0 #)- in case gen# nk loop2 (T# 0# 0#) of+ loop2 (T# i j) | isTrue# (i ==# n) = (# T# i j, 0 #)+ | isTrue# (j ==# k) = loop2 (T# (i +# 1#) 0#)+ | otherwise = (# T# i (j +# 1#), loop i j 0# 0 #)+ in case gen# steps loop2 (T# 0# 0#) of (# _, r #) -> r+ where+ getStepsAndIx :: forall (ns :: [Nat])+ . PrimArray t (DataFrame t ns)+ => Dims ns+ -> DataFrame t ns+ -> Either t CumulDims+ -> (Int# -> t, CumulDims)+ getStepsAndIx _ df (Right cds) = ((`ix#` df), cds)+ getStepsAndIx ds _ (Left e) = (\_ -> e, cumulDims ds)+ conSteps (CumulDims xs) (CumulDims ys) = case conSteps' xs ys of+ (W# n, W# m, W# k, zs)+ -> (# word2Int# n, word2Int# m, word2Int# k, CumulDims zs #)+ conSteps' :: [Word] -> [Word] -> (Word, Word, Word, [Word])+ conSteps' [m, _] (_:ys@(k:_)) = (1, m, k, ys)+ conSteps' (nm:ns) cys+ | (_, m, k, ys) <- conSteps' ns cys+ , n <- nm `quot` m+ = (n, m, k, n*k : ys )+ conSteps' _ _ = error "Numeric.DataFrame.Contraction: impossible match" data T# = T# Int# Int#
− src/Numeric/DataFrame/Family.hs
@@ -1,9 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE TypeFamilies #-}--- | The very core of DataFrame: definition of the data family.-module Numeric.DataFrame.Family ( DataFrame ) where---- | Keep data in a primitive data frame--- and maintain information about Dimensions in the type system-data family DataFrame (t :: l) (xs :: [k])
src/Numeric/DataFrame/IO.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-}@@ -17,8 +16,6 @@ -- Copyright : (c) Artem Chirkin -- License : BSD3 ----- Maintainer : chirkin@arch.ethz.ch--- -- Mutable DataFrames living in IO. -- -----------------------------------------------------------------------------@@ -27,6 +24,7 @@ ( IODataFrame (XIOFrame), SomeIODataFrame (..) , newDataFrame, newPinnedDataFrame , copyDataFrame, copyMutableDataFrame+ , copyDataFrame', copyMutableDataFrame' , freezeDataFrame, unsafeFreezeDataFrame , thawDataFrame, thawPinDataFrame, unsafeThawDataFrame , writeDataFrame, writeDataFrameOff@@ -35,15 +33,14 @@ ) where -import GHC.Base-import GHC.IO (IO (..))-import GHC.Ptr (Ptr (..))+import GHC.Base+import GHC.IO (IO (..))+import GHC.Ptr (Ptr (..)) -import Numeric.DataFrame.Family-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Mutable-import Numeric.Dimensions-import Numeric.PrimBytes+import Numeric.DataFrame.Internal.Mutable+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.Type+import Numeric.Dimensions -- | Mutable DataFrame that lives in IO.@@ -80,31 +77,69 @@ -- | Copy one DataFrame into another mutable DataFrame at specified position.-copyDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat)- (bs :: [Nat]) (asbs :: [Nat])- . ( PrimBytes t- , PrimBytes (DataFrame t (as +: b'))+--+-- In contrast to @copyMDataFrame'@, this function allows to copy over a range of contiguous+-- indices over a single dimension.+-- For example, you can write a 3x4 matrix into a 7x4 matrix, starting at indices 0..3.+copyDataFrame :: forall (t :: Type)+ (b :: Nat) (bi :: Nat) (bd :: Nat)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])+ . ( b ~ (bi + bd - 1)+ , PrimBytes t+ , PrimBytes (DataFrame t (bd :+ bs)) , ConcatList as (b :+ bs) asbs- , Dimensions (b :+ bs) )- => DataFrame t (as +: b') -> Idxs (b :+ bs) -> IODataFrame t asbs -> IO ()-copyDataFrame df ei (IODataFrame mdf) = IO (copyDataFrame# df ei mdf)+ => Idxs (as +: bi) -> DataFrame t (bd :+ bs)+ -> IODataFrame t asbs -> IO ()+copyDataFrame ei df (IODataFrame mdf) = IO (copyDataFrame# ei df mdf) {-# INLINE copyDataFrame #-} -- | Copy one mutable DataFrame into another mutable DataFrame at specified position.-copyMutableDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat)- (bs :: [Nat]) (asbs :: [Nat])- . ( PrimBytes t+--+-- In contrast to @copyMDataFrame'@, this function allows to copy over a range of contiguous+-- indices over a single dimension.+-- For example, you can write a 3x4 matrix into a 7x4 matrix, starting at indices 0..3.+copyMutableDataFrame :: forall (t :: Type)+ (b :: Nat) (bi :: Nat) (bd :: Nat)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])+ . ( b ~ (bi + bd - 1)+ , PrimBytes t , ConcatList as (b :+ bs) asbs- , Dimensions (b :+ bs) )- => IODataFrame t (as +: b') -> Idxs (b :+ bs)+ => Idxs (as +: bi) -> IODataFrame t (bd :+ bs) -> IODataFrame t asbs -> IO ()-copyMutableDataFrame (IODataFrame mdfA) ei (IODataFrame mdfB)- = IO (copyMDataFrame# mdfA ei mdfB)+copyMutableDataFrame ei (IODataFrame mdfA) (IODataFrame mdfB)+ = IO (copyMDataFrame# ei mdfA mdfB) {-# INLINE copyMutableDataFrame #-} +-- | Copy one DataFrame into another mutable DataFrame at specified position.+--+-- This is a simpler version of @copyDataFrame@ that allows to copy over one index at a time.+copyDataFrame' :: forall (t :: Type)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])+ . ( PrimBytes t+ , PrimBytes (DataFrame t bs)+ , ConcatList as bs asbs+ )+ => Idxs as -> DataFrame t bs+ -> IODataFrame t asbs -> IO ()+copyDataFrame' ei df (IODataFrame mdf) = IO (copyDataFrame'# ei df mdf)+{-# INLINE copyDataFrame' #-} +-- | Copy one mutable DataFrame into another mutable DataFrame at specified position.+--+-- This is a simpler version of @copyDataFrame@ that allows to copy over one index at a time.+copyMutableDataFrame' :: forall (t :: Type)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])+ . ( PrimBytes t+ , ConcatList as bs asbs+ )+ => Idxs as -> IODataFrame t bs+ -> IODataFrame t asbs -> IO ()+copyMutableDataFrame' ei (IODataFrame mdfA) (IODataFrame mdfB)+ = IO (copyMDataFrame'# ei mdfA mdfB)+{-# INLINE copyMutableDataFrame' #-}+ -- | Make a mutable DataFrame immutable, without copying. unsafeFreezeDataFrame :: forall (t :: Type) (ns :: [Nat]) . PrimArray t (DataFrame t ns)@@ -122,7 +157,7 @@ -- | Create a new mutable DataFrame and copy content of immutable one in there. thawDataFrame :: forall (t :: Type) (ns :: [Nat])- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> IO (IODataFrame t ns) thawDataFrame df = IODataFrame <$> IO (thawDataFrame# df) {-# INLINE thawDataFrame #-}@@ -130,14 +165,15 @@ -- | Create a new mutable DataFrame and copy content of immutable one in there. -- The result array is pinned and aligned. thawPinDataFrame :: forall (t :: Type) (ns :: [Nat])- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> IO (IODataFrame t ns) thawPinDataFrame df = IODataFrame <$> IO (thawPinDataFrame# df) {-# INLINE thawPinDataFrame #-} -- | UnsafeCoerces an underlying byte array. unsafeThawDataFrame :: forall (t :: Type) (ns :: [Nat])- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . ( Dimensions ns+ , PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> IO (IODataFrame t ns) unsafeThawDataFrame df = IODataFrame <$> IO (unsafeThawDataFrame# df) {-# INLINE unsafeThawDataFrame #-}@@ -145,7 +181,7 @@ -- | Write a single element at the specified index writeDataFrame :: forall t (ns :: [Nat])- . ( PrimBytes t, Dimensions ns )+ . PrimBytes t => IODataFrame t ns -> Idxs ns -> DataFrame t ('[] :: [Nat]) -> IO () writeDataFrame (IODataFrame mdf) ei = IO . writeDataFrame# mdf ei . unsafeCoerce# {-# INLINE writeDataFrame #-}@@ -153,7 +189,7 @@ -- | Read a single element at the specified index readDataFrame :: forall (t :: Type) (ns :: [Nat])- . ( PrimBytes t, Dimensions ns )+ . PrimBytes t => IODataFrame t ns -> Idxs ns -> IO (DataFrame t ('[] :: [Nat])) readDataFrame (IODataFrame mdf) = unsafeCoerce# . IO . readDataFrame# mdf {-# INLINE readDataFrame #-}@@ -177,6 +213,18 @@ {-# INLINE readDataFrameOff #-} +-- | Check if the byte array wrapped by this DataFrame is pinned,+-- which means cannot be relocated by GC.+isDataFramePinned :: forall (k :: Type) (t :: Type) (ns :: [k])+ . KnownDimKind k+ => IODataFrame t ns -> Bool+isDataFramePinned df = case dimKind @k of+ DimNat -> case df of+ IODataFrame x -> isDataFramePinned# x+ DimXNat -> case df of+ XIOFrame (IODataFrame x) -> isDataFramePinned# x++ -- | Allow arbitrary IO operations on a pointer to the beginning of the data -- keeping the data from garbage collecting until the arg function returns. --@@ -185,7 +233,7 @@ -- -- Warning: use this function on a pinned DataFrame only; -- otherwise, the data may be relocated before the arg fun finishes.-withDataFramePtr :: forall (t :: Type) (ns :: [k]) (r :: Type)+withDataFramePtr :: forall (k :: Type) (t :: Type) (ns :: [k]) (r :: Type) . (PrimBytes t, KnownDimKind k) => IODataFrame t ns -> ( Ptr t -> IO r )@@ -197,15 +245,3 @@ DimXNat -> case df of XIOFrame (IODataFrame x) -> IO $ withDataFramePtr# x (\p -> case k (Ptr p) of IO f -> f)----- | Check if the byte array wrapped by this DataFrame is pinned,--- which means cannot be relocated by GC.-isDataFramePinned :: forall (t :: Type) (ns :: [k])- . KnownDimKind k- => IODataFrame t ns -> Bool-isDataFramePinned df = case dimKind @k of- DimNat -> case df of- IODataFrame x -> isDataFramePinned# x- DimXNat -> case df of- XIOFrame (IODataFrame x) -> isDataFramePinned# x
− src/Numeric/DataFrame/Internal/Array.hs
@@ -1,26 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Numeric.DataFrame.Internal.Array--- Copyright : (c) Artem Chirkin--- License : BSD3------ Maintainer : chirkin@arch.ethz.ch------ Low-level implementations of data frames-----------------------------------------------------------------------------------module Numeric.DataFrame.Internal.Array- ( module Numeric.DataFrame.Internal.Array.Family- ) where--import Numeric.DataFrame.Internal.Array.Family--- import Numeric.DataFrame.Internal.Array.Family.ArrayBase ()---- import Numeric.DataFrame.Internal.Array.Family.FloatX2 ()--- import Numeric.DataFrame.Internal.Array.Family.FloatX3 ()--- import Numeric.DataFrame.Internal.Array.Family.FloatX4 ()------ import Numeric.DataFrame.Internal.Array.Family.DoubleX2 ()--- import Numeric.DataFrame.Internal.Array.Family.DoubleX3 ()--- import Numeric.DataFrame.Internal.Array.Family.DoubleX4 ()
− src/Numeric/DataFrame/Internal/Array/Class.hs
@@ -1,51 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Class- ( PrimArray (..)- , ixOff, unsafeFromFlatList- ) where--import GHC.Base (ByteArray#, Int#, Int (..))-import Numeric.PrimBytes---class PrimBytes t => PrimArray t a | a -> t where- -- | Broadcast element into array- broadcast :: t -> a- -- | Index an array given an offset- ix# :: Int# -> a -> t- -- | Generate an array using an accumulator funtion- gen# :: Int# -- ^ number of elements, not checked!- -- Avoid using this argument if possible.- -> (s -> (# s, t #))- -> s -> (# s, a #)- -- | update a single element in an array given an offset- upd# :: Int# -- ^ number of elements, not checked!- -- Avoid using this argument if possible.- -> Int# -> t -> a -> a-- -- | Offset of an array in number of elements- elemOffset :: a -> Int#-- -- | Number of elements in an array.- -- Returns zero if this information is not available at runtime.- -- This is possible only if all elements are same in an array.- elemSize0 :: a -> Int#-- -- | Get array by its offset and size in a ByteArray.- -- Both offset and size are given in element number.- fromElems :: Int# -> Int# -> ByteArray# -> a---- | Index array by an integer offset (starting from 0).-ixOff :: PrimArray t a => Int -> a -> t-ixOff (I# i) = ix# i---- | Construct an array from a flat list and length-unsafeFromFlatList :: PrimArray t a => Int -> [t] -> a-unsafeFromFlatList (I# n) vs = case gen# n f vs of (# _, r #) -> r- where- f [] = (# [], undefined #)- f (x:xs) = (# xs, x #)
− src/Numeric/DataFrame/Internal/Array/Family.hs
@@ -1,216 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeOperators #-}--------------------------------------------------------------------------------- |--- Module : Numeric.DataFrame.Internal.Array.Family--- Copyright : (c) Artem Chirkin--- License : BSD3------ Maintainer : chirkin@arch.ethz.ch--------------------------------------------------------------------------------------module Numeric.DataFrame.Internal.Array.Family- ( Array, ScalarBase (..), ArrayBase (..)- , ArraySingleton (..)- , ArraySing (..), aSingEv, inferASing- , inferPrimElem, inferPrim, inferEq, inferShow, inferOrd, inferNum- , inferFractional, inferFloating- ) where---import GHC.Base---import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.Family.ArrayBase-import Numeric.DataFrame.Internal.Array.Family.DoubleX2-import Numeric.DataFrame.Internal.Array.Family.DoubleX3-import Numeric.DataFrame.Internal.Array.Family.DoubleX4-import Numeric.DataFrame.Internal.Array.Family.FloatX2-import Numeric.DataFrame.Internal.Array.Family.FloatX3-import Numeric.DataFrame.Internal.Array.Family.FloatX4-import Numeric.DataFrame.Internal.Array.Family.ScalarBase-import Numeric.Dimensions-import Numeric.PrimBytes----- | This type family aggregates all types used for arrays with different--- dimensioinality.--- The family is injective; thus, it is possible to get type family instance--- given the data constructor (and vice versa).--- If GHC knows the dimensionality of an array at compile time, it chooses--- a more efficient specialized instance of Array, e.g. Scalar newtype wrapper.--- Otherwise, it falls back to the generic ArrayBase implementation.------ Data family would not work here, because it would give overlapping instances.-type family Array (t :: Type) (ds :: [Nat]) = (v :: Type) | v -> t ds where- Array t '[] = ScalarBase t- Array Float '[2] = FloatX2- Array Float '[3] = FloatX3- Array Float '[4] = FloatX4- Array Double '[2] = DoubleX2- Array Double '[3] = DoubleX3- Array Double '[4] = DoubleX4- Array t ds = ArrayBase t ds---- | A framework for using Array type family instances.-class ArraySingleton (t :: Type) (ds :: [Nat]) where- -- | Get Array type family instance- aSing :: ArraySing t ds--data ArraySing t (ds :: [Nat]) where- AScalar :: (Array t ds ~ ScalarBase t) => ArraySing t '[]- AF2 :: (Array t ds ~ FloatX2) => ArraySing Float '[2]- AF3 :: (Array t ds ~ FloatX3) => ArraySing Float '[3]- AF4 :: (Array t ds ~ FloatX4) => ArraySing Float '[4]- AD2 :: (Array t ds ~ DoubleX2) => ArraySing Double '[2]- AD3 :: (Array t ds ~ DoubleX3) => ArraySing Double '[3]- AD4 :: (Array t ds ~ DoubleX4) => ArraySing Double '[4]- ABase :: ( Array t ds ~ ArrayBase t ds- , PrimBytes t- ) => ArraySing t ds--deriving instance Eq (ArraySing t ds)-deriving instance Ord (ArraySing t ds)-deriving instance Show (ArraySing t ds)------ | This function does GHC's magic to convert user-supplied `aSing` function--- to create an instance of `ArraySingleton` typeclass at runtime.--- The trick is taken from Edward Kmett's reflection library explained--- in https://www.schoolofhaskell.com/user/thoughtpolice/using-reflection-reifyArraySing :: forall r t ds- . ArraySing t ds -> ( ArraySingleton t ds => r) -> r-reifyArraySing as k- = unsafeCoerce# (MagicArraySing k :: MagicArraySing t ds r) as-{-# INLINE reifyArraySing #-}-newtype MagicArraySing t (ds :: [Nat]) r- = MagicArraySing (ArraySingleton t ds => r)---- | Use `ArraySing` GADT to construct an `ArraySingleton` dictionary.--- In other words, bring an evidence of `ArraySingleton` instance into--- a scope at runtime.-aSingEv :: ArraySing t ds -> Evidence (ArraySingleton t ds)-aSingEv ds = reifyArraySing ds E-{-# INLINE aSingEv #-}---- | Use `ArraySing` GADT to construct an `ArraySingleton` dictionary.--- The same as `aSingEv`, but relies on `PrimBytes` and `Dimensions`.-inferASing :: forall t ds- . (PrimBytes t, Dimensions ds)- => Evidence (ArraySingleton t ds)-inferASing = case (dims @_ @ds, primTag @t undefined) of- (U, _) -> E- (d :* U, PTagFloat)- | Just E <- sameDim (D @2) d -> E- | Just E <- sameDim (D @3) d -> E- | Just E <- sameDim (D @4) d -> E- (d :* U, PTagDouble)- | Just E <- sameDim (D @2) d -> E- | Just E <- sameDim (D @3) d -> E- | Just E <- sameDim (D @4) d -> E- _ -> case (unsafeCoerce# (E @(ds ~ ds)) :: Evidence (ds ~ '[0])) of E -> E-{-# INLINE inferASing #-}---instance {-# OVERLAPPABLE #-}- (Array t ds ~ ArrayBase t ds, PrimBytes t)- => ArraySingleton t ds where- aSing = ABase-instance {-# OVERLAPPING #-} ArraySingleton t '[] where- aSing = AScalar-instance {-# OVERLAPPING #-} ArraySingleton Float '[2] where- aSing = AF2-instance {-# OVERLAPPING #-} ArraySingleton Float '[3] where- aSing = AF3-instance {-# OVERLAPPING #-} ArraySingleton Float '[4] where- aSing = AF4-instance {-# OVERLAPPING #-} ArraySingleton Double '[2] where- aSing = AD2-instance {-# OVERLAPPING #-} ArraySingleton Double '[3] where- aSing = AD3-instance {-# OVERLAPPING #-} ArraySingleton Double '[4] where- aSing = AD4---- | This is a special function, because Scalar does not require PrimBytes.--- That is why the dimension list in the argument is not empty.-inferPrimElem :: forall t d ds- . ArraySingleton t (d ': ds)- => Evidence (PrimBytes t)-inferPrimElem = case (aSing :: ArraySing t (d ': ds)) of- AF2 -> E- AF3 -> E- AF4 -> E- AD2 -> E- AD3 -> E- AD4 -> E- ABase -> E---- Rather verbose way to show that there is an instance of a required type class--- for every instance of the type family.-#define WITNESS case (aSing :: ArraySing t ds) of {\- AScalar -> E;\- AF2 -> E;\- AF3 -> E;\- AF4 -> E;\- AD2 -> E;\- AD3 -> E;\- AD4 -> E;\- ABase -> E}--inferPrim :: forall t ds- . ( PrimBytes t- , ArraySingleton t ds- , Dimensions ds- )- => Evidence (PrimBytes (Array t ds), PrimArray t (Array t ds))-inferPrim = WITNESS--inferEq :: forall t ds- . (Eq t, ArraySingleton t ds)- => Evidence (Eq (Array t ds))-inferEq = WITNESS--inferOrd :: forall t ds- . (Ord t, ArraySingleton t ds)- => Evidence (Ord (Array t ds))-inferOrd = WITNESS--inferNum :: forall t ds- . (Num t, ArraySingleton t ds)- => Evidence (Num (Array t ds))-inferNum = WITNESS--inferFractional :: forall t ds- . (Fractional t, ArraySingleton t ds)- => Evidence (Fractional (Array t ds))-inferFractional = WITNESS--inferFloating :: forall t ds- . (Floating t, ArraySingleton t ds)- => Evidence (Floating (Array t ds))-inferFloating = WITNESS--inferShow :: forall t ds- . (Show t, Dimensions ds, ArraySingleton t ds)- => Evidence (Show (Array t ds))-inferShow = WITNESS
− src/Numeric/DataFrame/Internal/Array/Family/ArrayBase.hs
@@ -1,498 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UnboxedSums #-}-{-# LANGUAGE UnboxedTuples #-}--module Numeric.DataFrame.Internal.Array.Family.ArrayBase- ( ArrayBase (..)- ) where--import Data.Int-import Data.Word-import GHC.Base hiding (foldr)-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.Dimensions-import Numeric.PrimBytes---- | Generic Array implementation.--- This array can reside in plain `ByteArray#` and can share the @ByteArray#@--- with other arrays.--- However, byte offset in the @ByteArray#@ must be multiple of the element size.-data ArrayBase (t :: Type) (ds :: [Nat])- = ArrayBase- (# t- -- Same value for each element;- -- this is the cheapest way to initialize an array.- -- It is also used for Num instances to avoid dependency on Dimensions.- | (# Int# -- Offset measured in elements.- , Int# -- Number of elements.- , ByteArray# -- Content.- , Evidence (PrimBytes t)- #)- #)---instance (PrimBytes t, Dimensions ds) => PrimBytes (ArrayBase t ds) where- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Float ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Double ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int8 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int16 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int32 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Int64 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word8 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word16 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word32 ds) #-}- {-# SPECIALIZE instance Dimensions ds => PrimBytes (ArrayBase Word64 ds) #-}-- getBytes (ArrayBase a ) = case a of- (# t | #)- | W# nw <- totalDim' @ds- , n <- word2Int# nw- , tbs <- byteSize t -> go tbs (tbs *# n) t- (# | (# _, _, arr, _ #) #) ->- -- very weird trick with touch# allows to workaround GHC bug- -- "internal error: ARR_WORDS object entered!"- -- TODO: report this- case runRW# (\s -> (# touch# arr s, arr #)) of (# _, ba #) -> ba- where- go tbs bsize t = case runRW#- ( \s0 -> case newByteArray# bsize s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( loop# 0# tbs bsize (\i -> writeBytes mba i t) s1 )- ) of (# _, ba #) -> ba- {-# NOINLINE go #-}- {-# INLINE getBytes #-}-- fromBytes bOff ba- | W# nw <- totalDim' @ds- , n <- word2Int# nw- , tbs <- byteSize (undefined :: t)- , (# offN, offRem #) <- quotRemInt# bOff tbs- = case offRem of- 0# -> ArrayBase (# | (# offN, n , ba, E #) #)- _ -> go n (tbs *# n)- where- go n bsize = case runRW#- ( \s0 -> case ( if isTrue# (isByteArrayPinned# ba)- then newAlignedPinnedByteArray# bsize- (byteAlign @t undefined)- else newByteArray# bsize- ) s0- of- (# s1, mba #) -> unsafeFreezeByteArray# mba- (copyByteArray# ba bOff mba 0# bsize s1)- ) of (# _, r #) -> ArrayBase (# | (# 0# , n , r, E #) #)- {-# NOINLINE go #-}- {-# INLINE fromBytes #-}-- readBytes mba bOff s0- | W# nw <- totalDim' @ds- , n <- word2Int# nw- , tbs <- byteSize (undefined :: t)- , bsize <- tbs *# n- = case newByteArray# bsize s0 of- (# s1, mba1 #) -> case unsafeFreezeByteArray# mba1- (copyMutableByteArray# mba bOff mba1 0# bsize s1) of- (# s2, ba #) -> (# s2, ArrayBase (# | (# 0# , n , ba, E #) #) #)- {-# INLINE readBytes #-}-- writeBytes mba bOff (ArrayBase c)- | tbs <- byteSize (undefined :: t) = case c of- (# t | #) | W# n <- totalDim' @ds ->- loop# bOff tbs (bOff +# word2Int# n *# tbs) (\i -> writeBytes mba i t)- (# | (# offN, n, arr, _ #) #) ->- copyByteArray# arr (offN *# tbs) mba bOff (n *# tbs)- {-# INLINE writeBytes #-}-- readAddr addr s0- | W# nw <- totalDim' @ds- , n <- word2Int# nw- , tbs <- byteSize (undefined :: t)- , bsize <- tbs *# n- = case newByteArray# bsize s0 of- (# s1, mba1 #) -> case unsafeFreezeByteArray# mba1- (copyAddrToByteArray# addr mba1 0# bsize s1) of- (# s2, ba #) -> (# s2, ArrayBase (# | (# 0# , n , ba, E #) #) #)- {-# INLINE readAddr #-}-- writeAddr (ArrayBase c) addr- | tbs <- byteSize (undefined :: t) = case c of- (# t | #) | W# n <- totalDim' @ds ->- loop# 0# tbs (word2Int# n *# tbs) (\i -> writeAddr t (plusAddr# addr i))- (# | (# offN, n, arr, _ #) #) ->- copyByteArrayToAddr# arr (offN *# tbs) addr (n *# tbs)- {-# INLINE writeAddr #-}--- byteSize _ = case totalDim' @ds of -- WARNING: slow!- W# n -> byteSize (undefined :: t) *# word2Int# n- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign (undefined :: t)- {-# INLINE byteAlign #-}-- byteOffset (ArrayBase a) = case a of- (# _ | #) -> 0#- (# | (# off, _, _, _ #) #) -> off *# byteSize (undefined :: t)- {-# INLINE byteOffset #-}-- indexArray ba off- | W# nw <- totalDim' @ds- , n <- word2Int# nw- = ArrayBase (# | (# off *# n, n, ba, E #) #)- {-# INLINE indexArray #-}------ | Accumulates only idempotent operations!--- Being applied to FromScalars, executes only once!--- Here, idempotance means: assuming @f a b = g x@, @g (g x) = g x@------ Also, I assume the sizes of arrays are the same-accumV2Idempotent :: a- -> (t -> t -> a -> a)- -> ArrayBase t ds -> ArrayBase t ds -> a-accumV2Idempotent x f- (ArrayBase (# a | #))- (ArrayBase (# b | #))- = f a b x-accumV2Idempotent x f- a@(ArrayBase (# | (# _, nA, _, E #) #))- b@(ArrayBase (# | (# _, nB, _, _ #) #))- = loop1a# (minInt# nA nB) (\i -> f (ix# i a) (ix# i b)) x-accumV2Idempotent x f- (ArrayBase (# a | #))- b@(ArrayBase (# | (# _, n, _, E #) #))- = loop1a# n (\i -> f a (ix# i b)) x-accumV2Idempotent x f- a@(ArrayBase (# | (# _, n, _, E #) #))- (ArrayBase (# b | #))- = loop1a# n (\i -> f (ix# i a) b) x-{-# INLINE accumV2Idempotent #-}--mapV :: (t -> t) -> ArrayBase t ds -> ArrayBase t ds-mapV f (ArrayBase (# t | #))- = ArrayBase (# f t | #)-mapV f x@(ArrayBase (# | (# offN, n, ba, E #) #))- | tbs <- byteSize (undefEl x)- = go (tbs *# n)- where- go bsize = case runRW#- ( \s0 -> case newByteArray# bsize s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( loop1# n- (\i -> writeArray mba i (f (indexArray ba (offN +# i)))) s1- )- ) of (# _, r #) -> ArrayBase (# | (# 0#, n, r, E #) #)- {-# NOINLINE go #-}-{-# INLINE mapV #-}---zipV :: (t -> t -> t)- -> ArrayBase t ds -> ArrayBase t ds -> ArrayBase t ds-zipV f (ArrayBase (# x | #)) b = mapV (f x) b-zipV f a (ArrayBase (# y | #)) = mapV (`f` y) a-zipV f a@(ArrayBase (# | (# oa, na, ba, E #) #))- (ArrayBase (# | (# ob, nb, bb, _ #) #))- | n <- minInt# na nb- = go n (byteSize (undefEl a) *# n)- where- go n bsize = case runRW#- ( \s0 -> case newByteArray# bsize s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( loop1# n- (\i -> writeArray mba i- (f (indexArray ba (oa +# i))- (indexArray bb (ob +# i))- )- ) s1- )- ) of (# _, r #) -> ArrayBase (# | (# 0#, n, r, E #) #)- {-# NOINLINE go #-}-{-# INLINE zipV #-}----- TODO: to improve performance, I can either compare bytearrays using memcmp--- or implement early termination if the first elements do not match.--- On the other hand, hopefully @(&&)@ and @(||)@ ops take care of that.-instance Eq t => Eq (ArrayBase t ds) where- {-# SPECIALIZE instance Eq (ArrayBase Float ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Double ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Int ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Word ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Int8 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Int16 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Int32 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Int64 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Word8 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Word16 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Word32 ds) #-}- {-# SPECIALIZE instance Eq (ArrayBase Word64 ds) #-}- (==) = accumV2Idempotent True (\x y r -> r && x == y)- (/=) = accumV2Idempotent False (\x y r -> r || x /= y)---- | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord t => Ord (ArrayBase t ds) where- {-# SPECIALIZE instance Ord (ArrayBase Float ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Double ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Int ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Word ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Int8 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Int16 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Int32 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Int64 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Word8 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Word16 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Word32 ds) #-}- {-# SPECIALIZE instance Ord (ArrayBase Word64 ds) #-}- -- | Partiall ordering: all elements GT- (>) = accumV2Idempotent True (\x y r -> r && x > y)- {-# INLINE (>) #-}- -- | Partiall ordering: all elements LT- (<) = accumV2Idempotent True (\x y r -> r && x < y)- {-# INLINE (<) #-}- -- | Partiall ordering: all elements GE- (>=) = accumV2Idempotent True (\x y r -> r && x >= y)- {-# INLINE (>=) #-}- -- | Partiall ordering: all elements LE- (<=) = accumV2Idempotent True (\x y r -> r && x <= y)- {-# INLINE (<=) #-}- -- | Compare lexicographically- compare = accumV2Idempotent EQ (\x y -> flip mappend (compare x y))- {-# INLINE compare #-}- -- | Element-wise minimum- min = zipV min- {-# INLINE min #-}- -- | Element-wise maximum- max = zipV max- {-# INLINE max #-}--instance (Dimensions ds, Show t)- => Show (ArrayBase t ds) where- show x = case dims @_ @ds of- U -> "{ " ++ show (ix U x) ++ " }"- Dim :* U -> ('{' :) . drop 1 $- foldr (\i s -> ", " ++ show (ix i x) ++ s) " }"- [minBound .. maxBound]- (Dim :: Dim n) :* (Dim :: Dim m) :* (Dims :: Dims dss) ->- let loopInner :: Idxs dss -> Idxs '[n,m] -> String- loopInner ods (n:*m:*_) = ('{' :) . drop 2 $- foldr (\i ss -> '\n':- foldr (\j s ->- ", " ++ show (ix (i :* j :* ods) x) ++ s- ) ss [1..m]- ) " }" [1..n]- loopOuter :: Idxs dss -> String -> String- loopOuter U s = "\n" ++ loopInner U maxBound ++ s- loopOuter ds s = "\n(i j" ++ drop 4 (show ds) ++ "):\n"- ++ loopInner ds maxBound ++ s- in drop 1 $ foldr loopOuter "" [minBound..maxBound]--instance {-# OVERLAPPING #-} Bounded (ArrayBase Double ds) where- maxBound = ArrayBase (# inftyD | #)- minBound = ArrayBase (# negate inftyD | #)--instance {-# OVERLAPPING #-} Bounded (ArrayBase Float ds) where- maxBound = ArrayBase (# inftyF | #)- minBound = ArrayBase (# negate inftyF | #)--instance {-# OVERLAPPABLE #-} Bounded t => Bounded (ArrayBase t ds) where- {-# SPECIALIZE instance Bounded (ArrayBase Int ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Word ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Int8 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Int16 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Int32 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Int64 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Word8 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Word16 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Word32 ds) #-}- {-# SPECIALIZE instance Bounded (ArrayBase Word64 ds) #-}- maxBound = ArrayBase (# maxBound | #)- minBound = ArrayBase (# minBound | #)--instance Num t => Num (ArrayBase t ds) where- {-# SPECIALIZE instance Num (ArrayBase Float ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Double ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Int ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Word ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Int8 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Int16 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Int32 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Int64 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Word8 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Word16 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Word32 ds) #-}- {-# SPECIALIZE instance Num (ArrayBase Word64 ds) #-}- (+) = zipV (+)- {-# INLINE (+) #-}- (-) = zipV (-)- {-# INLINE (-) #-}- (*) = zipV (*)- {-# INLINE (*) #-}- negate = mapV negate- {-# INLINE negate #-}- abs = mapV abs- {-# INLINE abs #-}- signum = mapV signum- {-# INLINE signum #-}- fromInteger i = ArrayBase (# fromInteger i | #)- {-# INLINE fromInteger #-}--instance Fractional t => Fractional (ArrayBase t ds) where- {-# SPECIALIZE instance Fractional (ArrayBase Float ds) #-}- {-# SPECIALIZE instance Fractional (ArrayBase Double ds) #-}- (/) = zipV (/)- {-# INLINE (/) #-}- recip = mapV recip- {-# INLINE recip #-}- fromRational r = ArrayBase (# fromRational r | #)- {-# INLINE fromRational #-}---instance Floating t => Floating (ArrayBase t ds) where- {-# SPECIALIZE instance Floating (ArrayBase Float ds) #-}- {-# SPECIALIZE instance Floating (ArrayBase Double ds) #-}- pi = ArrayBase (# pi | #)- {-# INLINE pi #-}- exp = mapV exp- {-# INLINE exp #-}- log = mapV log- {-# INLINE log #-}- sqrt = mapV sqrt- {-# INLINE sqrt #-}- sin = mapV sin- {-# INLINE sin #-}- cos = mapV cos- {-# INLINE cos #-}- tan = mapV tan- {-# INLINE tan #-}- asin = mapV asin- {-# INLINE asin #-}- acos = mapV acos- {-# INLINE acos #-}- atan = mapV atan- {-# INLINE atan #-}- sinh = mapV sinh- {-# INLINE sinh #-}- cosh = mapV cosh- {-# INLINE cosh #-}- tanh = mapV tanh- {-# INLINE tanh #-}- (**) = zipV (**)- {-# INLINE (**) #-}- logBase = zipV logBase- {-# INLINE logBase #-}- asinh = mapV asinh- {-# INLINE asinh #-}- acosh = mapV acosh- {-# INLINE acosh #-}- atanh = mapV atanh- {-# INLINE atanh #-}--instance PrimBytes t => PrimArray t (ArrayBase t ds) where- {-# SPECIALIZE instance PrimArray Float (ArrayBase Float ds) #-}- {-# SPECIALIZE instance PrimArray Double (ArrayBase Double ds) #-}- {-# SPECIALIZE instance PrimArray Int (ArrayBase Int ds) #-}- {-# SPECIALIZE instance PrimArray Word (ArrayBase Word ds) #-}- {-# SPECIALIZE instance PrimArray Int8 (ArrayBase Int8 ds) #-}- {-# SPECIALIZE instance PrimArray Int16 (ArrayBase Int16 ds) #-}- {-# SPECIALIZE instance PrimArray Int32 (ArrayBase Int32 ds) #-}- {-# SPECIALIZE instance PrimArray Int64 (ArrayBase Int64 ds) #-}- {-# SPECIALIZE instance PrimArray Word8 (ArrayBase Word8 ds) #-}- {-# SPECIALIZE instance PrimArray Word16 (ArrayBase Word16 ds) #-}- {-# SPECIALIZE instance PrimArray Word32 (ArrayBase Word32 ds) #-}- {-# SPECIALIZE instance PrimArray Word64 (ArrayBase Word64 ds) #-}-- broadcast t = ArrayBase (# t | #)- {-# INLINE broadcast #-}-- ix# i (ArrayBase a) = case a of- (# t | #) -> t- (# | (# off, _, arr, _ #) #) -> indexArray arr (off +# i)- {-# INLINE ix# #-}-- gen# n f z0 = go (byteSize @t undefined *# n)- where- go bsize = case runRW#- ( \s0 -> case newByteArray# bsize s0 of- (# s1, mba #) -> case loop0 mba 0# z0 s1 of- (# s2, z1 #) -> case unsafeFreezeByteArray# mba s2 of- (# s3, ba #) -> (# s3, (# z1, ba #) #)- ) of (# _, (# z1, ba #) #) -> (# z1, ArrayBase (# | (# 0# , n , ba, E #) #) #)- {-# NOINLINE go #-}- loop0 mba i z s- | isTrue# (i ==# n) = (# s, z #)- | otherwise = case f z of- (# z', x #) -> loop0 mba (i +# 1#) z' (writeArray mba i x s)- {-# INLINE gen# #-}-- upd# n i x (ArrayBase (# a | #)) = go (byteSize x)- where- go tbs = case runRW#- ( \s0 -> case newByteArray# (tbs *# n) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- (writeArray mba i x- (loop1# n (\j -> writeArray mba j a) s1)- )- ) of (# _, r #) -> ArrayBase (# | (# 0# , n , r, E #) #)- {-# NOINLINE go #-}- upd# _ i x (ArrayBase (# | (# offN , n , ba, E #) #)) = go (byteSize x)- where- go tbs = case runRW#- ( \s0 -> case newByteArray# (tbs *# n) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- (writeArray mba i x- (copyByteArray# ba (offN *# tbs) mba 0# (tbs *# n) s1)- )- ) of (# _, r #) -> ArrayBase (# | (# 0# , n , r, E #) #)- {-# NOINLINE go #-}- {-# INLINE upd# #-}-- elemOffset (ArrayBase a) = case a of- (# _ | #) -> 0#- (# | (# off, _, _, _ #) #) -> off- {-# INLINE elemOffset #-}-- elemSize0 (ArrayBase a) = case a of- (# _ | #) -> 0#- (# | (# _, n, _, _ #) #) -> n- {-# INLINE elemSize0 #-}-- fromElems off n ba = ArrayBase (# | (# off , n , ba, E #) #)- {-# INLINE fromElems #-}--------------------------------------------------------------------------------------- * Utility functions------------------------------------------------------------------------------------ix :: Dimensions ds => Idxs ds -> ArrayBase t ds -> t-ix i (ArrayBase a) = case a of- (# t | #) -> t- (# | (# off, _, arr, E #) #) -> case fromEnum i of- I# i# -> indexArray arr (off +# i#)-{-# INLINE ix #-}---undefEl :: ArrayBase t ds -> t-undefEl = const undefined
− src/Numeric/DataFrame/Internal/Array/Family/DoubleX2.hs
@@ -1,333 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Family.DoubleX2 (DoubleX2 (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.PrimBytes---data DoubleX2 = DoubleX2# Double# Double#---instance Bounded DoubleX2 where- maxBound = case inftyD of D# x -> DoubleX2# x x- minBound = case negate inftyD of D# x -> DoubleX2# x x---instance Show DoubleX2 where- show (DoubleX2# a1 a2)- = "{ " ++ show (D# a1)- ++ ", " ++ show (D# a2)- ++ " }"----instance Eq DoubleX2 where-- DoubleX2# a1 a2 == DoubleX2# b1 b2 =- isTrue#- ( (a1 ==## b1)- `andI#` (a2 ==## b2)- )- {-# INLINE (==) #-}-- DoubleX2# a1 a2 /= DoubleX2# b1 b2 =- isTrue#- ( (a1 /=## b1)- `orI#` (a2 /=## b2)- )- {-# INLINE (/=) #-}------ | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord DoubleX2 where- DoubleX2# a1 a2 > DoubleX2# b1 b2 =- isTrue#- ( (a1 >## b1)- `andI#` (a2 >## b2)- )- {-# INLINE (>) #-}-- DoubleX2# a1 a2 < DoubleX2# b1 b2 =- isTrue#- ( (a1 <## b1)- `andI#` (a2 <## b2)- )- {-# INLINE (<) #-}-- DoubleX2# a1 a2 >= DoubleX2# b1 b2 =- isTrue#- ( (a1 >=## b1)- `andI#` (a2 >=## b2)- )- {-# INLINE (>=) #-}-- DoubleX2# a1 a2 <= DoubleX2# b1 b2 =- isTrue#- ( (a1 <=## b1)- `andI#` (a2 <=## b2)- )- {-# INLINE (<=) #-}-- -- | Compare lexicographically- compare (DoubleX2# a1 a2) (DoubleX2# b1 b2)- | isTrue# (a1 >## b1) = GT- | isTrue# (a1 <## b1) = LT- | isTrue# (a2 >## b2) = GT- | isTrue# (a2 <## b2) = LT- | otherwise = EQ- {-# INLINE compare #-}-- -- | Element-wise minimum- min (DoubleX2# a1 a2) (DoubleX2# b1 b2) = DoubleX2#- (if isTrue# (a1 >## b1) then b1 else a1)- (if isTrue# (a2 >## b2) then b2 else a2)- {-# INLINE min #-}-- -- | Element-wise maximum- max (DoubleX2# a1 a2) (DoubleX2# b1 b2) = DoubleX2#- (if isTrue# (a1 >## b1) then a1 else b1)- (if isTrue# (a2 >## b2) then a2 else b2)- {-# INLINE max #-}------ | element-wise operations for vectors-instance Num DoubleX2 where-- DoubleX2# a1 a2 + DoubleX2# b1 b2- = DoubleX2# ((+##) a1 b1) ((+##) a2 b2)- {-# INLINE (+) #-}-- DoubleX2# a1 a2 - DoubleX2# b1 b2- = DoubleX2# ((-##) a1 b1) ((-##) a2 b2)- {-# INLINE (-) #-}-- DoubleX2# a1 a2 * DoubleX2# b1 b2- = DoubleX2# ((*##) a1 b1) ((*##) a2 b2)- {-# INLINE (*) #-}-- negate (DoubleX2# a1 a2) = DoubleX2#- (negateDouble# a1) (negateDouble# a2)- {-# INLINE negate #-}-- abs (DoubleX2# a1 a2)- = DoubleX2#- (if isTrue# (a1 >=## 0.0##) then a1 else negateDouble# a1)- (if isTrue# (a2 >=## 0.0##) then a2 else negateDouble# a2)- {-# INLINE abs #-}-- signum (DoubleX2# a1 a2)- = DoubleX2# (if isTrue# (a1 >## 0.0##)- then 1.0##- else if isTrue# (a1 <## 0.0##) then -1.0## else 0.0## )- (if isTrue# (a2 >## 0.0##)- then 1.0##- else if isTrue# (a2 <## 0.0##) then -1.0## else 0.0## )- {-# INLINE signum #-}-- fromInteger n = case fromInteger n of D# x -> DoubleX2# x x- {-# INLINE fromInteger #-}----instance Fractional DoubleX2 where-- DoubleX2# a1 a2 / DoubleX2# b1 b2 = DoubleX2#- ((/##) a1 b1) ((/##) a2 b2)- {-# INLINE (/) #-}-- recip (DoubleX2# a1 a2) = DoubleX2#- ((/##) 1.0## a1) ((/##) 1.0## a2)- {-# INLINE recip #-}-- fromRational r = case fromRational r of D# x -> DoubleX2# x x- {-# INLINE fromRational #-}----instance Floating DoubleX2 where-- pi = DoubleX2#- 3.141592653589793238##- 3.141592653589793238##- {-# INLINE pi #-}-- exp (DoubleX2# a1 a2) = DoubleX2#- (expDouble# a1) (expDouble# a2)- {-# INLINE exp #-}-- log (DoubleX2# a1 a2) = DoubleX2#- (logDouble# a1) (logDouble# a2)- {-# INLINE log #-}-- sqrt (DoubleX2# a1 a2) = DoubleX2#- (sqrtDouble# a1) (sqrtDouble# a2)- {-# INLINE sqrt #-}-- sin (DoubleX2# a1 a2) = DoubleX2#- (sinDouble# a1) (sinDouble# a2)- {-# INLINE sin #-}-- cos (DoubleX2# a1 a2) = DoubleX2#- (cosDouble# a1) (cosDouble# a2)- {-# INLINE cos #-}-- tan (DoubleX2# a1 a2) = DoubleX2#- (tanDouble# a1) (tanDouble# a2)- {-# INLINE tan #-}-- asin (DoubleX2# a1 a2) = DoubleX2#- (asinDouble# a1) (asinDouble# a2)- {-# INLINE asin #-}-- acos (DoubleX2# a1 a2) = DoubleX2#- (acosDouble# a1) (acosDouble# a2)- {-# INLINE acos #-}-- atan (DoubleX2# a1 a2) = DoubleX2#- (atanDouble# a1) (atanDouble# a2)- {-# INLINE atan #-}-- sinh (DoubleX2# a1 a2) = DoubleX2#- (sinhDouble# a1) (sinhDouble# a2)- {-# INLINE sinh #-}-- cosh (DoubleX2# a1 a2) = DoubleX2#- (coshDouble# a1) (coshDouble# a2)- {-# INLINE cosh #-}-- tanh (DoubleX2# a1 a2) = DoubleX2#- (tanhDouble# a1) (tanhDouble# a2)- {-# INLINE tanh #-}-- DoubleX2# a1 a2 ** DoubleX2# b1 b2 = DoubleX2#- ((**##) a1 b1) ((**##) a2 b2)- {-# INLINE (**) #-}-- logBase x y = log y / log x- {-# INLINE logBase #-}-- asinh x = log (x + sqrt (1.0+x*x))- {-# INLINE asinh #-}-- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- {-# INLINE acosh #-}-- atanh x = 0.5 * log ((1.0+x) / (1.0-x))- {-# INLINE atanh #-}---- offset in bytes is S times bigger than offset in prim elements,--- when S is power of two, this is equal to shift-#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 3#-#define ELEM_N 2--instance PrimBytes DoubleX2 where-- getBytes (DoubleX2# a1 a2) = case runRW#- ( \s0 -> case newByteArray# (byteSize @DoubleX2 undefined) s0 of- (# s1, marr #) -> case writeDoubleArray# marr 0# a1 s1 of- s2 -> case writeDoubleArray# marr 1# a2 s2 of- s3 -> unsafeFreezeByteArray# marr s3- ) of (# _, a #) -> a- {-# INLINE getBytes #-}-- fromBytes off arr- | i <- BOFF_TO_PRIMOFF(off)- = DoubleX2#- (indexDoubleArray# arr i)- (indexDoubleArray# arr (i +# 1#))- {-# INLINE fromBytes #-}-- readBytes mba off s0- | i <- BOFF_TO_PRIMOFF(off)- = case readDoubleArray# mba i s0 of- (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> (# s2, DoubleX2# a1 a2 #)- {-# INLINE readBytes #-}-- writeBytes mba off (DoubleX2# a1 a2) s- | i <- BOFF_TO_PRIMOFF(off)- = writeDoubleArray# mba (i +# 1#) a2- ( writeDoubleArray# mba i a1 s )- {-# INLINE writeBytes #-}-- readAddr addr s0- = case readDoubleOffAddr# addr 0# s0 of- (# s1, a1 #) -> case readDoubleOffAddr# addr 1# s1 of- (# s2, a2 #) -> (# s2, DoubleX2# a1 a2 #)- {-# INLINE readAddr #-}-- writeAddr (DoubleX2# a1 a2) addr s- = writeDoubleOffAddr# addr 1# a2- ( writeDoubleOffAddr# addr 0# a1 s )- {-# INLINE writeAddr #-}-- byteSize _ = byteSize @Double undefined *# ELEM_N#- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign @Double undefined- {-# INLINE byteAlign #-}-- byteOffset _ = 0#- {-# INLINE byteOffset #-}-- indexArray ba off- | i <- off *# ELEM_N#- = DoubleX2#- (indexDoubleArray# ba i)- (indexDoubleArray# ba (i +# 1#))- {-# INLINE indexArray #-}-- readArray mba off s0- | i <- off *# ELEM_N#- = case readDoubleArray# mba i s0 of- (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> (# s2, DoubleX2# a1 a2 #)- {-# INLINE readArray #-}-- writeArray mba off (DoubleX2# a1 a2) s- | i <- off *# ELEM_N#- = writeDoubleArray# mba (i +# 1#) a2- ( writeDoubleArray# mba i a1 s )- {-# INLINE writeArray #-}---instance PrimArray Double DoubleX2 where-- broadcast (D# x) = DoubleX2# x x- {-# INLINE broadcast #-}-- ix# 0# (DoubleX2# a1 _) = D# a1- ix# 1# (DoubleX2# _ a2) = D# a2- ix# _ _ = undefined- {-# INLINE ix# #-}-- gen# _ f s0 = case f s0 of- (# s1, D# a1 #) -> case f s1 of- (# s2, D# a2 #) -> (# s2, DoubleX2# a1 a2 #)--- upd# _ 0# (D# q) (DoubleX2# _ y) = DoubleX2# q y- upd# _ 1# (D# q) (DoubleX2# x _) = DoubleX2# x q- upd# _ _ _ x = x- {-# INLINE upd# #-}-- elemOffset _ = 0#- {-# INLINE elemOffset #-}-- elemSize0 _ = ELEM_N#- {-# INLINE elemSize0 #-}-- fromElems off _ ba = DoubleX2#- (indexDoubleArray# ba off)- (indexDoubleArray# ba (off +# 1#))- {-# INLINE fromElems #-}
− src/Numeric/DataFrame/Internal/Array/Family/DoubleX3.hs
@@ -1,362 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Family.DoubleX3 (DoubleX3 (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.PrimBytes---data DoubleX3 = DoubleX3# Double# Double# Double#---instance Bounded DoubleX3 where- maxBound = case inftyD of D# x -> DoubleX3# x x x- minBound = case negate inftyD of D# x -> DoubleX3# x x x---instance Show DoubleX3 where- show (DoubleX3# a1 a2 a3)- = "{ " ++ show (D# a1)- ++ ", " ++ show (D# a2)- ++ ", " ++ show (D# a3)- ++ " }"----instance Eq DoubleX3 where-- DoubleX3# a1 a2 a3 == DoubleX3# b1 b2 b3 =- isTrue#- ( (a1 ==## b1)- `andI#` (a2 ==## b2)- `andI#` (a3 ==## b3)- )- {-# INLINE (==) #-}-- DoubleX3# a1 a2 a3 /= DoubleX3# b1 b2 b3 =- isTrue#- ( (a1 /=## b1)- `orI#` (a2 /=## b2)- `orI#` (a3 /=## b3)- )- {-# INLINE (/=) #-}------ | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord DoubleX3 where- DoubleX3# a1 a2 a3 > DoubleX3# b1 b2 b3 =- isTrue#- ( (a1 >## b1)- `andI#` (a2 >## b2)- `andI#` (a3 >## b3)- )- {-# INLINE (>) #-}-- DoubleX3# a1 a2 a3 < DoubleX3# b1 b2 b3 =- isTrue#- ( (a1 <## b1)- `andI#` (a2 <## b2)- `andI#` (a3 <## b3)- )- {-# INLINE (<) #-}-- DoubleX3# a1 a2 a3 >= DoubleX3# b1 b2 b3 =- isTrue#- ( (a1 >=## b1)- `andI#` (a2 >=## b2)- `andI#` (a3 >=## b3)- )- {-# INLINE (>=) #-}-- DoubleX3# a1 a2 a3 <= DoubleX3# b1 b2 b3 =- isTrue#- ( (a1 <=## b1)- `andI#` (a2 <=## b2)- `andI#` (a3 <=## b3)- )- {-# INLINE (<=) #-}-- -- | Compare lexicographically- compare (DoubleX3# a1 a2 a3) (DoubleX3# b1 b2 b3)- | isTrue# (a1 >## b1) = GT- | isTrue# (a1 <## b1) = LT- | isTrue# (a2 >## b2) = GT- | isTrue# (a2 <## b2) = LT- | isTrue# (a3 >## b3) = GT- | isTrue# (a3 <## b3) = LT- | otherwise = EQ- {-# INLINE compare #-}-- -- | Element-wise minimum- min (DoubleX3# a1 a2 a3) (DoubleX3# b1 b2 b3) = DoubleX3#- (if isTrue# (a1 >## b1) then b1 else a1)- (if isTrue# (a2 >## b2) then b2 else a2)- (if isTrue# (a3 >## b3) then b3 else a3)- {-# INLINE min #-}-- -- | Element-wise maximum- max (DoubleX3# a1 a2 a3) (DoubleX3# b1 b2 b3) = DoubleX3#- (if isTrue# (a1 >## b1) then a1 else b1)- (if isTrue# (a2 >## b2) then a2 else b2)- (if isTrue# (a3 >## b3) then a3 else b3)- {-# INLINE max #-}------ | element-wise operations for vectors-instance Num DoubleX3 where-- DoubleX3# a1 a2 a3 + DoubleX3# b1 b2 b3- = DoubleX3# ((+##) a1 b1) ((+##) a2 b2) ((+##) a3 b3)- {-# INLINE (+) #-}-- DoubleX3# a1 a2 a3 - DoubleX3# b1 b2 b3- = DoubleX3# ((-##) a1 b1) ((-##) a2 b2) ((-##) a3 b3)- {-# INLINE (-) #-}-- DoubleX3# a1 a2 a3 * DoubleX3# b1 b2 b3- = DoubleX3# ((*##) a1 b1) ((*##) a2 b2) ((*##) a3 b3)- {-# INLINE (*) #-}-- negate (DoubleX3# a1 a2 a3) = DoubleX3#- (negateDouble# a1) (negateDouble# a2) (negateDouble# a3)- {-# INLINE negate #-}-- abs (DoubleX3# a1 a2 a3)- = DoubleX3#- (if isTrue# (a1 >=## 0.0##) then a1 else negateDouble# a1)- (if isTrue# (a2 >=## 0.0##) then a2 else negateDouble# a2)- (if isTrue# (a3 >=## 0.0##) then a3 else negateDouble# a3)- {-# INLINE abs #-}-- signum (DoubleX3# a1 a2 a3)- = DoubleX3# (if isTrue# (a1 >## 0.0##)- then 1.0##- else if isTrue# (a1 <## 0.0##) then -1.0## else 0.0## )- (if isTrue# (a2 >## 0.0##)- then 1.0##- else if isTrue# (a2 <## 0.0##) then -1.0## else 0.0## )- (if isTrue# (a3 >## 0.0##)- then 1.0##- else if isTrue# (a3 <## 0.0##) then -1.0## else 0.0## )- {-# INLINE signum #-}-- fromInteger n = case fromInteger n of D# x -> DoubleX3# x x x- {-# INLINE fromInteger #-}----instance Fractional DoubleX3 where-- DoubleX3# a1 a2 a3 / DoubleX3# b1 b2 b3 = DoubleX3#- ((/##) a1 b1) ((/##) a2 b2) ((/##) a3 b3)- {-# INLINE (/) #-}-- recip (DoubleX3# a1 a2 a3) = DoubleX3#- ((/##) 1.0## a1) ((/##) 1.0## a2) ((/##) 1.0## a3)- {-# INLINE recip #-}-- fromRational r = case fromRational r of D# x -> DoubleX3# x x x- {-# INLINE fromRational #-}----instance Floating DoubleX3 where-- pi = DoubleX3#- 3.141592653589793238##- 3.141592653589793238##- 3.141592653589793238##- {-# INLINE pi #-}-- exp (DoubleX3# a1 a2 a3) = DoubleX3#- (expDouble# a1) (expDouble# a2) (expDouble# a3)- {-# INLINE exp #-}-- log (DoubleX3# a1 a2 a3) = DoubleX3#- (logDouble# a1) (logDouble# a2) (logDouble# a3)- {-# INLINE log #-}-- sqrt (DoubleX3# a1 a2 a3) = DoubleX3#- (sqrtDouble# a1) (sqrtDouble# a2) (sqrtDouble# a3)- {-# INLINE sqrt #-}-- sin (DoubleX3# a1 a2 a3) = DoubleX3#- (sinDouble# a1) (sinDouble# a2) (sinDouble# a3)- {-# INLINE sin #-}-- cos (DoubleX3# a1 a2 a3) = DoubleX3#- (cosDouble# a1) (cosDouble# a2) (cosDouble# a3)- {-# INLINE cos #-}-- tan (DoubleX3# a1 a2 a3) = DoubleX3#- (tanDouble# a1) (tanDouble# a2) (tanDouble# a3)- {-# INLINE tan #-}-- asin (DoubleX3# a1 a2 a3) = DoubleX3#- (asinDouble# a1) (asinDouble# a2) (asinDouble# a3)- {-# INLINE asin #-}-- acos (DoubleX3# a1 a2 a3) = DoubleX3#- (acosDouble# a1) (acosDouble# a2) (acosDouble# a3)- {-# INLINE acos #-}-- atan (DoubleX3# a1 a2 a3) = DoubleX3#- (atanDouble# a1) (atanDouble# a2) (atanDouble# a3)- {-# INLINE atan #-}-- sinh (DoubleX3# a1 a2 a3) = DoubleX3#- (sinhDouble# a1) (sinhDouble# a2) (sinhDouble# a3)- {-# INLINE sinh #-}-- cosh (DoubleX3# a1 a2 a3) = DoubleX3#- (coshDouble# a1) (coshDouble# a2) (coshDouble# a3)- {-# INLINE cosh #-}-- tanh (DoubleX3# a1 a2 a3) = DoubleX3#- (tanhDouble# a1) (tanhDouble# a2) (tanhDouble# a3)- {-# INLINE tanh #-}-- DoubleX3# a1 a2 a3 ** DoubleX3# b1 b2 b3 = DoubleX3#- ((**##) a1 b1) ((**##) a2 b2) ((**##) a3 b3)- {-# INLINE (**) #-}-- logBase x y = log y / log x- {-# INLINE logBase #-}-- asinh x = log (x + sqrt (1.0+x*x))- {-# INLINE asinh #-}-- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- {-# INLINE acosh #-}-- atanh x = 0.5 * log ((1.0+x) / (1.0-x))- {-# INLINE atanh #-}---- offset in bytes is S times bigger than offset in prim elements,--- when S is power of two, this is equal to shift-#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 3#-#define ELEM_N 3--instance PrimBytes DoubleX3 where-- getBytes (DoubleX3# a1 a2 a3) = case runRW#- ( \s0 -> case newByteArray# (byteSize @DoubleX3 undefined) s0 of- (# s1, marr #) -> case writeDoubleArray# marr 0# a1 s1 of- s2 -> case writeDoubleArray# marr 1# a2 s2 of- s3 -> case writeDoubleArray# marr 2# a3 s3 of- s4 -> unsafeFreezeByteArray# marr s4- ) of (# _, a #) -> a- {-# INLINE getBytes #-}-- fromBytes off arr- | i <- BOFF_TO_PRIMOFF(off)- = DoubleX3#- (indexDoubleArray# arr i)- (indexDoubleArray# arr (i +# 1#))- (indexDoubleArray# arr (i +# 2#))- {-# INLINE fromBytes #-}-- readBytes mba off s0- | i <- BOFF_TO_PRIMOFF(off)- = case readDoubleArray# mba i s0 of- (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)- {-# INLINE readBytes #-}-- writeBytes mba off (DoubleX3# a1 a2 a3) s- | i <- BOFF_TO_PRIMOFF(off)- = writeDoubleArray# mba (i +# 2#) a3- ( writeDoubleArray# mba (i +# 1#) a2- ( writeDoubleArray# mba i a1 s ))- {-# INLINE writeBytes #-}-- readAddr addr s0- = case readDoubleOffAddr# addr 0# s0 of- (# s1, a1 #) -> case readDoubleOffAddr# addr 1# s1 of- (# s2, a2 #) -> case readDoubleOffAddr# addr 2# s2 of- (# s3, a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)- {-# INLINE readAddr #-}-- writeAddr (DoubleX3# a1 a2 a3) addr s- = writeDoubleOffAddr# addr 2# a3- ( writeDoubleOffAddr# addr 1# a2- ( writeDoubleOffAddr# addr 0# a1 s ))- {-# INLINE writeAddr #-}-- byteSize _ = byteSize @Double undefined *# ELEM_N#- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign @Double undefined- {-# INLINE byteAlign #-}-- byteOffset _ = 0#- {-# INLINE byteOffset #-}-- indexArray ba off- | i <- off *# ELEM_N#- = DoubleX3#- (indexDoubleArray# ba i)- (indexDoubleArray# ba (i +# 1#))- (indexDoubleArray# ba (i +# 2#))- {-# INLINE indexArray #-}-- readArray mba off s0- | i <- off *# ELEM_N#- = case readDoubleArray# mba i s0 of- (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)- {-# INLINE readArray #-}-- writeArray mba off (DoubleX3# a1 a2 a3) s- | i <- off *# ELEM_N#- = writeDoubleArray# mba (i +# 2#) a3- ( writeDoubleArray# mba (i +# 1#) a2- ( writeDoubleArray# mba i a1 s ))- {-# INLINE writeArray #-}---instance PrimArray Double DoubleX3 where-- broadcast (D# x) = DoubleX3# x x x- {-# INLINE broadcast #-}-- ix# 0# (DoubleX3# a1 _ _) = D# a1- ix# 1# (DoubleX3# _ a2 _) = D# a2- ix# 2# (DoubleX3# _ _ a3) = D# a3- ix# _ _ = undefined- {-# INLINE ix# #-}-- gen# _ f s0 = case f s0 of- (# s1, D# a1 #) -> case f s1 of- (# s2, D# a2 #) -> case f s2 of- (# s3, D# a3 #) -> (# s3, DoubleX3# a1 a2 a3 #)--- upd# _ 0# (D# q) (DoubleX3# _ y z) = DoubleX3# q y z- upd# _ 1# (D# q) (DoubleX3# x _ z) = DoubleX3# x q z- upd# _ 2# (D# q) (DoubleX3# x y _) = DoubleX3# x y q- upd# _ _ _ x = x- {-# INLINE upd# #-}-- elemOffset _ = 0#- {-# INLINE elemOffset #-}-- elemSize0 _ = ELEM_N#- {-# INLINE elemSize0 #-}-- fromElems off _ ba = DoubleX3#- (indexDoubleArray# ba off)- (indexDoubleArray# ba (off +# 1#))- (indexDoubleArray# ba (off +# 2#))- {-# INLINE fromElems #-}
− src/Numeric/DataFrame/Internal/Array/Family/DoubleX4.hs
@@ -1,391 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Family.DoubleX4 (DoubleX4 (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.PrimBytes---data DoubleX4 = DoubleX4# Double# Double# Double# Double#---instance Bounded DoubleX4 where- maxBound = case inftyD of D# x -> DoubleX4# x x x x- minBound = case negate inftyD of D# x -> DoubleX4# x x x x---instance Show DoubleX4 where- show (DoubleX4# a1 a2 a3 a4)- = "{ " ++ show (D# a1)- ++ ", " ++ show (D# a2)- ++ ", " ++ show (D# a3)- ++ ", " ++ show (D# a4)- ++ " }"----instance Eq DoubleX4 where-- DoubleX4# a1 a2 a3 a4 == DoubleX4# b1 b2 b3 b4 =- isTrue#- ( (a1 ==## b1)- `andI#` (a2 ==## b2)- `andI#` (a3 ==## b3)- `andI#` (a4 ==## b4)- )- {-# INLINE (==) #-}-- DoubleX4# a1 a2 a3 a4 /= DoubleX4# b1 b2 b3 b4 =- isTrue#- ( (a1 /=## b1)- `orI#` (a2 /=## b2)- `orI#` (a3 /=## b3)- `orI#` (a4 /=## b4)- )- {-# INLINE (/=) #-}------ | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord DoubleX4 where- DoubleX4# a1 a2 a3 a4 > DoubleX4# b1 b2 b3 b4 =- isTrue#- ( (a1 >## b1)- `andI#` (a2 >## b2)- `andI#` (a3 >## b3)- `andI#` (a4 >## b4)- )- {-# INLINE (>) #-}-- DoubleX4# a1 a2 a3 a4 < DoubleX4# b1 b2 b3 b4 =- isTrue#- ( (a1 <## b1)- `andI#` (a2 <## b2)- `andI#` (a3 <## b3)- `andI#` (a4 <## b4)- )- {-# INLINE (<) #-}-- DoubleX4# a1 a2 a3 a4 >= DoubleX4# b1 b2 b3 b4 =- isTrue#- ( (a1 >=## b1)- `andI#` (a2 >=## b2)- `andI#` (a3 >=## b3)- `andI#` (a4 >=## b4)- )- {-# INLINE (>=) #-}-- DoubleX4# a1 a2 a3 a4 <= DoubleX4# b1 b2 b3 b4 =- isTrue#- ( (a1 <=## b1)- `andI#` (a2 <=## b2)- `andI#` (a3 <=## b3)- `andI#` (a4 <=## b4)- )- {-# INLINE (<=) #-}-- -- | Compare lexicographically- compare (DoubleX4# a1 a2 a3 a4) (DoubleX4# b1 b2 b3 b4)- | isTrue# (a1 >## b1) = GT- | isTrue# (a1 <## b1) = LT- | isTrue# (a2 >## b2) = GT- | isTrue# (a2 <## b2) = LT- | isTrue# (a3 >## b3) = GT- | isTrue# (a3 <## b3) = LT- | isTrue# (a4 >## b4) = GT- | isTrue# (a4 <## b4) = LT- | otherwise = EQ- {-# INLINE compare #-}-- -- | Element-wise minimum- min (DoubleX4# a1 a2 a3 a4) (DoubleX4# b1 b2 b3 b4) = DoubleX4#- (if isTrue# (a1 >## b1) then b1 else a1)- (if isTrue# (a2 >## b2) then b2 else a2)- (if isTrue# (a3 >## b3) then b3 else a3)- (if isTrue# (a4 >## b4) then b4 else a4)- {-# INLINE min #-}-- -- | Element-wise maximum- max (DoubleX4# a1 a2 a3 a4) (DoubleX4# b1 b2 b3 b4) = DoubleX4#- (if isTrue# (a1 >## b1) then a1 else b1)- (if isTrue# (a2 >## b2) then a2 else b2)- (if isTrue# (a3 >## b3) then a3 else b3)- (if isTrue# (a4 >## b4) then a4 else b4)- {-# INLINE max #-}------ | element-wise operations for vectors-instance Num DoubleX4 where-- DoubleX4# a1 a2 a3 a4 + DoubleX4# b1 b2 b3 b4- = DoubleX4# ((+##) a1 b1) ((+##) a2 b2) ((+##) a3 b3) ((+##) a4 b4)- {-# INLINE (+) #-}-- DoubleX4# a1 a2 a3 a4 - DoubleX4# b1 b2 b3 b4- = DoubleX4# ((-##) a1 b1) ((-##) a2 b2) ((-##) a3 b3) ((-##) a4 b4)- {-# INLINE (-) #-}-- DoubleX4# a1 a2 a3 a4 * DoubleX4# b1 b2 b3 b4- = DoubleX4# ((*##) a1 b1) ((*##) a2 b2) ((*##) a3 b3) ((*##) a4 b4)- {-# INLINE (*) #-}-- negate (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (negateDouble# a1) (negateDouble# a2) (negateDouble# a3) (negateDouble# a4)- {-# INLINE negate #-}-- abs (DoubleX4# a1 a2 a3 a4)- = DoubleX4#- (if isTrue# (a1 >=## 0.0##) then a1 else negateDouble# a1)- (if isTrue# (a2 >=## 0.0##) then a2 else negateDouble# a2)- (if isTrue# (a3 >=## 0.0##) then a3 else negateDouble# a3)- (if isTrue# (a4 >=## 0.0##) then a4 else negateDouble# a4)- {-# INLINE abs #-}-- signum (DoubleX4# a1 a2 a3 a4)- = DoubleX4# (if isTrue# (a1 >## 0.0##)- then 1.0##- else if isTrue# (a1 <## 0.0##) then -1.0## else 0.0## )- (if isTrue# (a2 >## 0.0##)- then 1.0##- else if isTrue# (a2 <## 0.0##) then -1.0## else 0.0## )- (if isTrue# (a3 >## 0.0##)- then 1.0##- else if isTrue# (a3 <## 0.0##) then -1.0## else 0.0## )- (if isTrue# (a4 >## 0.0##)- then 1.0##- else if isTrue# (a4 <## 0.0##) then -1.0## else 0.0## )- {-# INLINE signum #-}-- fromInteger n = case fromInteger n of D# x -> DoubleX4# x x x x- {-# INLINE fromInteger #-}----instance Fractional DoubleX4 where-- DoubleX4# a1 a2 a3 a4 / DoubleX4# b1 b2 b3 b4 = DoubleX4#- ((/##) a1 b1) ((/##) a2 b2) ((/##) a3 b3) ((/##) a4 b4)- {-# INLINE (/) #-}-- recip (DoubleX4# a1 a2 a3 a4) = DoubleX4#- ((/##) 1.0## a1) ((/##) 1.0## a2) ((/##) 1.0## a3) ((/##) 1.0## a4)- {-# INLINE recip #-}-- fromRational r = case fromRational r of D# x -> DoubleX4# x x x x- {-# INLINE fromRational #-}----instance Floating DoubleX4 where-- pi = DoubleX4#- 3.141592653589793238##- 3.141592653589793238##- 3.141592653589793238##- 3.141592653589793238##- {-# INLINE pi #-}-- exp (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (expDouble# a1) (expDouble# a2) (expDouble# a3) (expDouble# a4)- {-# INLINE exp #-}-- log (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (logDouble# a1) (logDouble# a2) (logDouble# a3) (logDouble# a4)- {-# INLINE log #-}-- sqrt (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (sqrtDouble# a1) (sqrtDouble# a2) (sqrtDouble# a3) (sqrtDouble# a4)- {-# INLINE sqrt #-}-- sin (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (sinDouble# a1) (sinDouble# a2) (sinDouble# a3) (sinDouble# a4)- {-# INLINE sin #-}-- cos (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (cosDouble# a1) (cosDouble# a2) (cosDouble# a3) (cosDouble# a4)- {-# INLINE cos #-}-- tan (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (tanDouble# a1) (tanDouble# a2) (tanDouble# a3) (tanDouble# a4)- {-# INLINE tan #-}-- asin (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (asinDouble# a1) (asinDouble# a2) (asinDouble# a3) (asinDouble# a4)- {-# INLINE asin #-}-- acos (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (acosDouble# a1) (acosDouble# a2) (acosDouble# a3) (acosDouble# a4)- {-# INLINE acos #-}-- atan (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (atanDouble# a1) (atanDouble# a2) (atanDouble# a3) (atanDouble# a4)- {-# INLINE atan #-}-- sinh (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (sinhDouble# a1) (sinhDouble# a2) (sinhDouble# a3) (sinhDouble# a4)- {-# INLINE sinh #-}-- cosh (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (coshDouble# a1) (coshDouble# a2) (coshDouble# a3) (coshDouble# a4)- {-# INLINE cosh #-}-- tanh (DoubleX4# a1 a2 a3 a4) = DoubleX4#- (tanhDouble# a1) (tanhDouble# a2) (tanhDouble# a3) (tanhDouble# a4)- {-# INLINE tanh #-}-- DoubleX4# a1 a2 a3 a4 ** DoubleX4# b1 b2 b3 b4 = DoubleX4#- ((**##) a1 b1) ((**##) a2 b2) ((**##) a3 b3) ((**##) a4 b4)- {-# INLINE (**) #-}-- logBase x y = log y / log x- {-# INLINE logBase #-}-- asinh x = log (x + sqrt (1.0+x*x))- {-# INLINE asinh #-}-- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- {-# INLINE acosh #-}-- atanh x = 0.5 * log ((1.0+x) / (1.0-x))- {-# INLINE atanh #-}---- offset in bytes is S times bigger than offset in prim elements,--- when S is power of two, this is equal to shift-#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 3#-#define ELEM_N 4--instance PrimBytes DoubleX4 where-- getBytes (DoubleX4# a1 a2 a3 a4) = case runRW#- ( \s0 -> case newByteArray# (byteSize @DoubleX4 undefined) s0 of- (# s1, marr #) -> case writeDoubleArray# marr 0# a1 s1 of- s2 -> case writeDoubleArray# marr 1# a2 s2 of- s3 -> case writeDoubleArray# marr 2# a3 s3 of- s4 -> case writeDoubleArray# marr 3# a4 s4 of- s5 -> unsafeFreezeByteArray# marr s5- ) of (# _, a #) -> a- {-# INLINE getBytes #-}-- fromBytes off arr- | i <- BOFF_TO_PRIMOFF(off)- = DoubleX4#- (indexDoubleArray# arr i)- (indexDoubleArray# arr (i +# 1#))- (indexDoubleArray# arr (i +# 2#))- (indexDoubleArray# arr (i +# 3#))- {-# INLINE fromBytes #-}-- readBytes mba off s0- | i <- BOFF_TO_PRIMOFF(off)- = case readDoubleArray# mba i s0 of- (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> case readDoubleArray# mba (i +# 3#) s3 of- (# s4, a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)- {-# INLINE readBytes #-}-- writeBytes mba off (DoubleX4# a1 a2 a3 a4) s- | i <- BOFF_TO_PRIMOFF(off)- = writeDoubleArray# mba (i +# 3#) a4- ( writeDoubleArray# mba (i +# 2#) a3- ( writeDoubleArray# mba (i +# 1#) a2- ( writeDoubleArray# mba i a1 s )))- {-# INLINE writeBytes #-}-- readAddr addr s0- = case readDoubleOffAddr# addr 0# s0 of- (# s1, a1 #) -> case readDoubleOffAddr# addr 1# s1 of- (# s2, a2 #) -> case readDoubleOffAddr# addr 2# s2 of- (# s3, a3 #) -> case readDoubleOffAddr# addr 3# s3 of- (# s4, a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)- {-# INLINE readAddr #-}-- writeAddr (DoubleX4# a1 a2 a3 a4) addr s- = writeDoubleOffAddr# addr 3# a4- ( writeDoubleOffAddr# addr 2# a3- ( writeDoubleOffAddr# addr 1# a2- ( writeDoubleOffAddr# addr 0# a1 s )))- {-# INLINE writeAddr #-}-- byteSize _ = byteSize @Double undefined *# ELEM_N#- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign @Double undefined- {-# INLINE byteAlign #-}-- byteOffset _ = 0#- {-# INLINE byteOffset #-}-- indexArray ba off- | i <- off *# ELEM_N#- = DoubleX4#- (indexDoubleArray# ba i)- (indexDoubleArray# ba (i +# 1#))- (indexDoubleArray# ba (i +# 2#))- (indexDoubleArray# ba (i +# 3#))- {-# INLINE indexArray #-}-- readArray mba off s0- | i <- off *# ELEM_N#- = case readDoubleArray# mba i s0 of- (# s1, a1 #) -> case readDoubleArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readDoubleArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> case readDoubleArray# mba (i +# 3#) s3 of- (# s4, a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)- {-# INLINE readArray #-}-- writeArray mba off (DoubleX4# a1 a2 a3 a4) s- | i <- off *# ELEM_N#- = writeDoubleArray# mba (i +# 3#) a4- ( writeDoubleArray# mba (i +# 2#) a3- ( writeDoubleArray# mba (i +# 1#) a2- ( writeDoubleArray# mba i a1 s )))- {-# INLINE writeArray #-}---instance PrimArray Double DoubleX4 where-- broadcast (D# x) = DoubleX4# x x x x- {-# INLINE broadcast #-}-- ix# 0# (DoubleX4# a1 _ _ _) = D# a1- ix# 1# (DoubleX4# _ a2 _ _) = D# a2- ix# 2# (DoubleX4# _ _ a3 _) = D# a3- ix# 3# (DoubleX4# _ _ _ a4) = D# a4- ix# _ _ = undefined- {-# INLINE ix# #-}-- gen# _ f s0 = case f s0 of- (# s1, D# a1 #) -> case f s1 of- (# s2, D# a2 #) -> case f s2 of- (# s3, D# a3 #) -> case f s3 of- (# s4, D# a4 #) -> (# s4, DoubleX4# a1 a2 a3 a4 #)--- upd# _ 0# (D# q) (DoubleX4# _ y z w) = DoubleX4# q y z w- upd# _ 1# (D# q) (DoubleX4# x _ z w) = DoubleX4# x q z w- upd# _ 2# (D# q) (DoubleX4# x y _ w) = DoubleX4# x y q w- upd# _ 3# (D# q) (DoubleX4# x y z _) = DoubleX4# x y z q- upd# _ _ _ x = x- {-# INLINE upd# #-}-- elemOffset _ = 0#- {-# INLINE elemOffset #-}-- elemSize0 _ = ELEM_N#- {-# INLINE elemSize0 #-}-- fromElems off _ ba = DoubleX4#- (indexDoubleArray# ba off)- (indexDoubleArray# ba (off +# 1#))- (indexDoubleArray# ba (off +# 2#))- (indexDoubleArray# ba (off +# 3#))- {-# INLINE fromElems #-}
− src/Numeric/DataFrame/Internal/Array/Family/FloatX2.hs
@@ -1,333 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Family.FloatX2 (FloatX2 (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.PrimBytes---data FloatX2 = FloatX2# Float# Float#---instance Bounded FloatX2 where- maxBound = case inftyF of F# x -> FloatX2# x x- minBound = case negate inftyF of F# x -> FloatX2# x x---instance Show FloatX2 where- show (FloatX2# a1 a2)- = "{ " ++ show (F# a1)- ++ ", " ++ show (F# a2)- ++ " }"----instance Eq FloatX2 where-- FloatX2# a1 a2 == FloatX2# b1 b2 =- isTrue#- ( (a1 `eqFloat#` b1)- `andI#` (a2 `eqFloat#` b2)- )- {-# INLINE (==) #-}-- FloatX2# a1 a2 /= FloatX2# b1 b2 =- isTrue#- ( (a1 `neFloat#` b1)- `orI#` (a2 `neFloat#` b2)- )- {-# INLINE (/=) #-}------ | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord FloatX2 where- FloatX2# a1 a2 > FloatX2# b1 b2 =- isTrue#- ( (a1 `gtFloat#` b1)- `andI#` (a2 `gtFloat#` b2)- )- {-# INLINE (>) #-}-- FloatX2# a1 a2 < FloatX2# b1 b2 =- isTrue#- ( (a1 `ltFloat#` b1)- `andI#` (a2 `ltFloat#` b2)- )- {-# INLINE (<) #-}-- FloatX2# a1 a2 >= FloatX2# b1 b2 =- isTrue#- ( (a1 `geFloat#` b1)- `andI#` (a2 `geFloat#` b2)- )- {-# INLINE (>=) #-}-- FloatX2# a1 a2 <= FloatX2# b1 b2 =- isTrue#- ( (a1 `leFloat#` b1)- `andI#` (a2 `leFloat#` b2)- )- {-# INLINE (<=) #-}-- -- | Compare lexicographically- compare (FloatX2# a1 a2) (FloatX2# b1 b2)- | isTrue# (a1 `gtFloat#` b1) = GT- | isTrue# (a1 `ltFloat#` b1) = LT- | isTrue# (a2 `gtFloat#` b2) = GT- | isTrue# (a2 `ltFloat#` b2) = LT- | otherwise = EQ- {-# INLINE compare #-}-- -- | Element-wise minimum- min (FloatX2# a1 a2) (FloatX2# b1 b2) = FloatX2#- (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)- (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)- {-# INLINE min #-}-- -- | Element-wise maximum- max (FloatX2# a1 a2) (FloatX2# b1 b2) = FloatX2#- (if isTrue# (a1 `gtFloat#` b1) then a1 else b1)- (if isTrue# (a2 `gtFloat#` b2) then a2 else b2)- {-# INLINE max #-}------ | element-wise operations for vectors-instance Num FloatX2 where-- FloatX2# a1 a2 + FloatX2# b1 b2- = FloatX2# (plusFloat# a1 b1) (plusFloat# a2 b2)- {-# INLINE (+) #-}-- FloatX2# a1 a2 - FloatX2# b1 b2- = FloatX2# (minusFloat# a1 b1) (minusFloat# a2 b2)- {-# INLINE (-) #-}-- FloatX2# a1 a2 * FloatX2# b1 b2- = FloatX2# (timesFloat# a1 b1) (timesFloat# a2 b2)- {-# INLINE (*) #-}-- negate (FloatX2# a1 a2) = FloatX2#- (negateFloat# a1) (negateFloat# a2)- {-# INLINE negate #-}-- abs (FloatX2# a1 a2)- = FloatX2#- (if isTrue# (a1 `geFloat#` 0.0#) then a1 else negateFloat# a1)- (if isTrue# (a2 `geFloat#` 0.0#) then a2 else negateFloat# a2)- {-# INLINE abs #-}-- signum (FloatX2# a1 a2)- = FloatX2# (if isTrue# (a1 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a1 `ltFloat#` 0.0#) then -1.0# else 0.0# )- (if isTrue# (a2 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a2 `ltFloat#` 0.0#) then -1.0# else 0.0# )- {-# INLINE signum #-}-- fromInteger n = case fromInteger n of F# x -> FloatX2# x x- {-# INLINE fromInteger #-}----instance Fractional FloatX2 where-- FloatX2# a1 a2 / FloatX2# b1 b2 = FloatX2#- (divideFloat# a1 b1) (divideFloat# a2 b2)- {-# INLINE (/) #-}-- recip (FloatX2# a1 a2) = FloatX2#- (divideFloat# 1.0# a1) (divideFloat# 1.0# a2)- {-# INLINE recip #-}-- fromRational r = case fromRational r of F# x -> FloatX2# x x- {-# INLINE fromRational #-}----instance Floating FloatX2 where-- pi = FloatX2#- 3.141592653589793238#- 3.141592653589793238#- {-# INLINE pi #-}-- exp (FloatX2# a1 a2) = FloatX2#- (expFloat# a1) (expFloat# a2)- {-# INLINE exp #-}-- log (FloatX2# a1 a2) = FloatX2#- (logFloat# a1) (logFloat# a2)- {-# INLINE log #-}-- sqrt (FloatX2# a1 a2) = FloatX2#- (sqrtFloat# a1) (sqrtFloat# a2)- {-# INLINE sqrt #-}-- sin (FloatX2# a1 a2) = FloatX2#- (sinFloat# a1) (sinFloat# a2)- {-# INLINE sin #-}-- cos (FloatX2# a1 a2) = FloatX2#- (cosFloat# a1) (cosFloat# a2)- {-# INLINE cos #-}-- tan (FloatX2# a1 a2) = FloatX2#- (tanFloat# a1) (tanFloat# a2)- {-# INLINE tan #-}-- asin (FloatX2# a1 a2) = FloatX2#- (asinFloat# a1) (asinFloat# a2)- {-# INLINE asin #-}-- acos (FloatX2# a1 a2) = FloatX2#- (acosFloat# a1) (acosFloat# a2)- {-# INLINE acos #-}-- atan (FloatX2# a1 a2) = FloatX2#- (atanFloat# a1) (atanFloat# a2)- {-# INLINE atan #-}-- sinh (FloatX2# a1 a2) = FloatX2#- (sinhFloat# a1) (sinhFloat# a2)- {-# INLINE sinh #-}-- cosh (FloatX2# a1 a2) = FloatX2#- (coshFloat# a1) (coshFloat# a2)- {-# INLINE cosh #-}-- tanh (FloatX2# a1 a2) = FloatX2#- (tanhFloat# a1) (tanhFloat# a2)- {-# INLINE tanh #-}-- FloatX2# a1 a2 ** FloatX2# b1 b2 = FloatX2#- (powerFloat# a1 b1) (powerFloat# a2 b2)- {-# INLINE (**) #-}-- logBase x y = log y / log x- {-# INLINE logBase #-}-- asinh x = log (x + sqrt (1.0+x*x))- {-# INLINE asinh #-}-- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- {-# INLINE acosh #-}-- atanh x = 0.5 * log ((1.0+x) / (1.0-x))- {-# INLINE atanh #-}---- offset in bytes is S times bigger than offset in prim elements,--- when S is power of two, this is equal to shift-#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 2#-#define ELEM_N 2--instance PrimBytes FloatX2 where-- getBytes (FloatX2# a1 a2) = case runRW#- ( \s0 -> case newByteArray# (byteSize @FloatX2 undefined) s0 of- (# s1, marr #) -> case writeFloatArray# marr 0# a1 s1 of- s2 -> case writeFloatArray# marr 1# a2 s2 of- s3 -> unsafeFreezeByteArray# marr s3- ) of (# _, a #) -> a- {-# INLINE getBytes #-}-- fromBytes off arr- | i <- BOFF_TO_PRIMOFF(off)- = FloatX2#- (indexFloatArray# arr i)- (indexFloatArray# arr (i +# 1#))- {-# INLINE fromBytes #-}-- readBytes mba off s0- | i <- BOFF_TO_PRIMOFF(off)- = case readFloatArray# mba i s0 of- (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> (# s2, FloatX2# a1 a2 #)- {-# INLINE readBytes #-}-- writeBytes mba off (FloatX2# a1 a2) s- | i <- BOFF_TO_PRIMOFF(off)- = writeFloatArray# mba (i +# 1#) a2- ( writeFloatArray# mba i a1 s )- {-# INLINE writeBytes #-}-- readAddr addr s0- = case readFloatOffAddr# addr 0# s0 of- (# s1, a1 #) -> case readFloatOffAddr# addr 1# s1 of- (# s2, a2 #) -> (# s2, FloatX2# a1 a2 #)- {-# INLINE readAddr #-}-- writeAddr (FloatX2# a1 a2) addr s- = writeFloatOffAddr# addr 1# a2- ( writeFloatOffAddr# addr 0# a1 s )- {-# INLINE writeAddr #-}-- byteSize _ = byteSize @Float undefined *# ELEM_N#- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign @Float undefined- {-# INLINE byteAlign #-}-- byteOffset _ = 0#- {-# INLINE byteOffset #-}-- indexArray ba off- | i <- off *# ELEM_N#- = FloatX2#- (indexFloatArray# ba i)- (indexFloatArray# ba (i +# 1#))- {-# INLINE indexArray #-}-- readArray mba off s0- | i <- off *# ELEM_N#- = case readFloatArray# mba i s0 of- (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> (# s2, FloatX2# a1 a2 #)- {-# INLINE readArray #-}-- writeArray mba off (FloatX2# a1 a2) s- | i <- off *# ELEM_N#- = writeFloatArray# mba (i +# 1#) a2- ( writeFloatArray# mba i a1 s )- {-# INLINE writeArray #-}---instance PrimArray Float FloatX2 where-- broadcast (F# x) = FloatX2# x x- {-# INLINE broadcast #-}-- ix# 0# (FloatX2# a1 _) = F# a1- ix# 1# (FloatX2# _ a2) = F# a2- ix# _ _ = undefined- {-# INLINE ix# #-}-- gen# _ f s0 = case f s0 of- (# s1, F# a1 #) -> case f s1 of- (# s2, F# a2 #) -> (# s2, FloatX2# a1 a2 #)--- upd# _ 0# (F# q) (FloatX2# _ y) = FloatX2# q y- upd# _ 1# (F# q) (FloatX2# x _) = FloatX2# x q- upd# _ _ _ x = x- {-# INLINE upd# #-}-- elemOffset _ = 0#- {-# INLINE elemOffset #-}-- elemSize0 _ = ELEM_N#- {-# INLINE elemSize0 #-}-- fromElems off _ ba = FloatX2#- (indexFloatArray# ba off)- (indexFloatArray# ba (off +# 1#))- {-# INLINE fromElems #-}
− src/Numeric/DataFrame/Internal/Array/Family/FloatX3.hs
@@ -1,362 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Family.FloatX3 (FloatX3 (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.PrimBytes---data FloatX3 = FloatX3# Float# Float# Float#---instance Bounded FloatX3 where- maxBound = case inftyF of F# x -> FloatX3# x x x- minBound = case negate inftyF of F# x -> FloatX3# x x x---instance Show FloatX3 where- show (FloatX3# a1 a2 a3)- = "{ " ++ show (F# a1)- ++ ", " ++ show (F# a2)- ++ ", " ++ show (F# a3)- ++ " }"----instance Eq FloatX3 where-- FloatX3# a1 a2 a3 == FloatX3# b1 b2 b3 =- isTrue#- ( (a1 `eqFloat#` b1)- `andI#` (a2 `eqFloat#` b2)- `andI#` (a3 `eqFloat#` b3)- )- {-# INLINE (==) #-}-- FloatX3# a1 a2 a3 /= FloatX3# b1 b2 b3 =- isTrue#- ( (a1 `neFloat#` b1)- `orI#` (a2 `neFloat#` b2)- `orI#` (a3 `neFloat#` b3)- )- {-# INLINE (/=) #-}------ | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord FloatX3 where- FloatX3# a1 a2 a3 > FloatX3# b1 b2 b3 =- isTrue#- ( (a1 `gtFloat#` b1)- `andI#` (a2 `gtFloat#` b2)- `andI#` (a3 `gtFloat#` b3)- )- {-# INLINE (>) #-}-- FloatX3# a1 a2 a3 < FloatX3# b1 b2 b3 =- isTrue#- ( (a1 `ltFloat#` b1)- `andI#` (a2 `ltFloat#` b2)- `andI#` (a3 `ltFloat#` b3)- )- {-# INLINE (<) #-}-- FloatX3# a1 a2 a3 >= FloatX3# b1 b2 b3 =- isTrue#- ( (a1 `geFloat#` b1)- `andI#` (a2 `geFloat#` b2)- `andI#` (a3 `geFloat#` b3)- )- {-# INLINE (>=) #-}-- FloatX3# a1 a2 a3 <= FloatX3# b1 b2 b3 =- isTrue#- ( (a1 `leFloat#` b1)- `andI#` (a2 `leFloat#` b2)- `andI#` (a3 `leFloat#` b3)- )- {-# INLINE (<=) #-}-- -- | Compare lexicographically- compare (FloatX3# a1 a2 a3) (FloatX3# b1 b2 b3)- | isTrue# (a1 `gtFloat#` b1) = GT- | isTrue# (a1 `ltFloat#` b1) = LT- | isTrue# (a2 `gtFloat#` b2) = GT- | isTrue# (a2 `ltFloat#` b2) = LT- | isTrue# (a3 `gtFloat#` b3) = GT- | isTrue# (a3 `ltFloat#` b3) = LT- | otherwise = EQ- {-# INLINE compare #-}-- -- | Element-wise minimum- min (FloatX3# a1 a2 a3) (FloatX3# b1 b2 b3) = FloatX3#- (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)- (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)- (if isTrue# (a3 `gtFloat#` b3) then b3 else a3)- {-# INLINE min #-}-- -- | Element-wise maximum- max (FloatX3# a1 a2 a3) (FloatX3# b1 b2 b3) = FloatX3#- (if isTrue# (a1 `gtFloat#` b1) then a1 else b1)- (if isTrue# (a2 `gtFloat#` b2) then a2 else b2)- (if isTrue# (a3 `gtFloat#` b3) then a3 else b3)- {-# INLINE max #-}------ | element-wise operations for vectors-instance Num FloatX3 where-- FloatX3# a1 a2 a3 + FloatX3# b1 b2 b3- = FloatX3# (plusFloat# a1 b1) (plusFloat# a2 b2) (plusFloat# a3 b3)- {-# INLINE (+) #-}-- FloatX3# a1 a2 a3 - FloatX3# b1 b2 b3- = FloatX3# (minusFloat# a1 b1) (minusFloat# a2 b2) (minusFloat# a3 b3)- {-# INLINE (-) #-}-- FloatX3# a1 a2 a3 * FloatX3# b1 b2 b3- = FloatX3# (timesFloat# a1 b1) (timesFloat# a2 b2) (timesFloat# a3 b3)- {-# INLINE (*) #-}-- negate (FloatX3# a1 a2 a3) = FloatX3#- (negateFloat# a1) (negateFloat# a2) (negateFloat# a3)- {-# INLINE negate #-}-- abs (FloatX3# a1 a2 a3)- = FloatX3#- (if isTrue# (a1 `geFloat#` 0.0#) then a1 else negateFloat# a1)- (if isTrue# (a2 `geFloat#` 0.0#) then a2 else negateFloat# a2)- (if isTrue# (a3 `geFloat#` 0.0#) then a3 else negateFloat# a3)- {-# INLINE abs #-}-- signum (FloatX3# a1 a2 a3)- = FloatX3# (if isTrue# (a1 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a1 `ltFloat#` 0.0#) then -1.0# else 0.0# )- (if isTrue# (a2 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a2 `ltFloat#` 0.0#) then -1.0# else 0.0# )- (if isTrue# (a3 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a3 `ltFloat#` 0.0#) then -1.0# else 0.0# )- {-# INLINE signum #-}-- fromInteger n = case fromInteger n of F# x -> FloatX3# x x x- {-# INLINE fromInteger #-}----instance Fractional FloatX3 where-- FloatX3# a1 a2 a3 / FloatX3# b1 b2 b3 = FloatX3#- (divideFloat# a1 b1) (divideFloat# a2 b2) (divideFloat# a3 b3)- {-# INLINE (/) #-}-- recip (FloatX3# a1 a2 a3) = FloatX3#- (divideFloat# 1.0# a1) (divideFloat# 1.0# a2) (divideFloat# 1.0# a3)- {-# INLINE recip #-}-- fromRational r = case fromRational r of F# x -> FloatX3# x x x- {-# INLINE fromRational #-}----instance Floating FloatX3 where-- pi = FloatX3#- 3.141592653589793238#- 3.141592653589793238#- 3.141592653589793238#- {-# INLINE pi #-}-- exp (FloatX3# a1 a2 a3) = FloatX3#- (expFloat# a1) (expFloat# a2) (expFloat# a3)- {-# INLINE exp #-}-- log (FloatX3# a1 a2 a3) = FloatX3#- (logFloat# a1) (logFloat# a2) (logFloat# a3)- {-# INLINE log #-}-- sqrt (FloatX3# a1 a2 a3) = FloatX3#- (sqrtFloat# a1) (sqrtFloat# a2) (sqrtFloat# a3)- {-# INLINE sqrt #-}-- sin (FloatX3# a1 a2 a3) = FloatX3#- (sinFloat# a1) (sinFloat# a2) (sinFloat# a3)- {-# INLINE sin #-}-- cos (FloatX3# a1 a2 a3) = FloatX3#- (cosFloat# a1) (cosFloat# a2) (cosFloat# a3)- {-# INLINE cos #-}-- tan (FloatX3# a1 a2 a3) = FloatX3#- (tanFloat# a1) (tanFloat# a2) (tanFloat# a3)- {-# INLINE tan #-}-- asin (FloatX3# a1 a2 a3) = FloatX3#- (asinFloat# a1) (asinFloat# a2) (asinFloat# a3)- {-# INLINE asin #-}-- acos (FloatX3# a1 a2 a3) = FloatX3#- (acosFloat# a1) (acosFloat# a2) (acosFloat# a3)- {-# INLINE acos #-}-- atan (FloatX3# a1 a2 a3) = FloatX3#- (atanFloat# a1) (atanFloat# a2) (atanFloat# a3)- {-# INLINE atan #-}-- sinh (FloatX3# a1 a2 a3) = FloatX3#- (sinhFloat# a1) (sinhFloat# a2) (sinhFloat# a3)- {-# INLINE sinh #-}-- cosh (FloatX3# a1 a2 a3) = FloatX3#- (coshFloat# a1) (coshFloat# a2) (coshFloat# a3)- {-# INLINE cosh #-}-- tanh (FloatX3# a1 a2 a3) = FloatX3#- (tanhFloat# a1) (tanhFloat# a2) (tanhFloat# a3)- {-# INLINE tanh #-}-- FloatX3# a1 a2 a3 ** FloatX3# b1 b2 b3 = FloatX3#- (powerFloat# a1 b1) (powerFloat# a2 b2) (powerFloat# a3 b3)- {-# INLINE (**) #-}-- logBase x y = log y / log x- {-# INLINE logBase #-}-- asinh x = log (x + sqrt (1.0+x*x))- {-# INLINE asinh #-}-- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- {-# INLINE acosh #-}-- atanh x = 0.5 * log ((1.0+x) / (1.0-x))- {-# INLINE atanh #-}---- offset in bytes is S times bigger than offset in prim elements,--- when S is power of two, this is equal to shift-#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 2#-#define ELEM_N 3--instance PrimBytes FloatX3 where-- getBytes (FloatX3# a1 a2 a3) = case runRW#- ( \s0 -> case newByteArray# (byteSize @FloatX3 undefined) s0 of- (# s1, marr #) -> case writeFloatArray# marr 0# a1 s1 of- s2 -> case writeFloatArray# marr 1# a2 s2 of- s3 -> case writeFloatArray# marr 2# a3 s3 of- s4 -> unsafeFreezeByteArray# marr s4- ) of (# _, a #) -> a- {-# INLINE getBytes #-}-- fromBytes off arr- | i <- BOFF_TO_PRIMOFF(off)- = FloatX3#- (indexFloatArray# arr i)- (indexFloatArray# arr (i +# 1#))- (indexFloatArray# arr (i +# 2#))- {-# INLINE fromBytes #-}-- readBytes mba off s0- | i <- BOFF_TO_PRIMOFF(off)- = case readFloatArray# mba i s0 of- (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> (# s3, FloatX3# a1 a2 a3 #)- {-# INLINE readBytes #-}-- writeBytes mba off (FloatX3# a1 a2 a3) s- | i <- BOFF_TO_PRIMOFF(off)- = writeFloatArray# mba (i +# 2#) a3- ( writeFloatArray# mba (i +# 1#) a2- ( writeFloatArray# mba i a1 s ))- {-# INLINE writeBytes #-}-- readAddr addr s0- = case readFloatOffAddr# addr 0# s0 of- (# s1, a1 #) -> case readFloatOffAddr# addr 1# s1 of- (# s2, a2 #) -> case readFloatOffAddr# addr 2# s2 of- (# s3, a3 #) -> (# s3, FloatX3# a1 a2 a3 #)- {-# INLINE readAddr #-}-- writeAddr (FloatX3# a1 a2 a3) addr s- = writeFloatOffAddr# addr 2# a3- ( writeFloatOffAddr# addr 1# a2- ( writeFloatOffAddr# addr 0# a1 s ))- {-# INLINE writeAddr #-}-- byteSize _ = byteSize @Float undefined *# ELEM_N#- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign @Float undefined- {-# INLINE byteAlign #-}-- byteOffset _ = 0#- {-# INLINE byteOffset #-}-- indexArray ba off- | i <- off *# ELEM_N#- = FloatX3#- (indexFloatArray# ba i)- (indexFloatArray# ba (i +# 1#))- (indexFloatArray# ba (i +# 2#))- {-# INLINE indexArray #-}-- readArray mba off s0- | i <- off *# ELEM_N#- = case readFloatArray# mba i s0 of- (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> (# s3, FloatX3# a1 a2 a3 #)- {-# INLINE readArray #-}-- writeArray mba off (FloatX3# a1 a2 a3) s- | i <- off *# ELEM_N#- = writeFloatArray# mba (i +# 2#) a3- ( writeFloatArray# mba (i +# 1#) a2- ( writeFloatArray# mba i a1 s ))- {-# INLINE writeArray #-}---instance PrimArray Float FloatX3 where-- broadcast (F# x) = FloatX3# x x x- {-# INLINE broadcast #-}-- ix# 0# (FloatX3# a1 _ _) = F# a1- ix# 1# (FloatX3# _ a2 _) = F# a2- ix# 2# (FloatX3# _ _ a3) = F# a3- ix# _ _ = undefined- {-# INLINE ix# #-}-- gen# _ f s0 = case f s0 of- (# s1, F# a1 #) -> case f s1 of- (# s2, F# a2 #) -> case f s2 of- (# s3, F# a3 #) -> (# s3, FloatX3# a1 a2 a3 #)--- upd# _ 0# (F# q) (FloatX3# _ y z) = FloatX3# q y z- upd# _ 1# (F# q) (FloatX3# x _ z) = FloatX3# x q z- upd# _ 2# (F# q) (FloatX3# x y _) = FloatX3# x y q- upd# _ _ _ x = x- {-# INLINE upd# #-}-- elemOffset _ = 0#- {-# INLINE elemOffset #-}-- elemSize0 _ = ELEM_N#- {-# INLINE elemSize0 #-}-- fromElems off _ ba = FloatX3#- (indexFloatArray# ba off)- (indexFloatArray# ba (off +# 1#))- (indexFloatArray# ba (off +# 2#))- {-# INLINE fromElems #-}
− src/Numeric/DataFrame/Internal/Array/Family/FloatX4.hs
@@ -1,420 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UnboxedTuples #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Numeric.DataFrame.Internal.Array.Family.FloatX4 (FloatX4 (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.DataFrame.SubSpace-import Numeric.Dimensions-import Numeric.PrimBytes---data FloatX4 = FloatX4# Float# Float# Float# Float#---instance Bounded FloatX4 where- maxBound = case inftyF of F# x -> FloatX4# x x x x- minBound = case negate inftyF of F# x -> FloatX4# x x x x---instance Show FloatX4 where- show (FloatX4# a1 a2 a3 a4)- = "{ " ++ show (F# a1)- ++ ", " ++ show (F# a2)- ++ ", " ++ show (F# a3)- ++ ", " ++ show (F# a4)- ++ " }"----instance Eq FloatX4 where-- FloatX4# a1 a2 a3 a4 == FloatX4# b1 b2 b3 b4 =- isTrue#- ( (a1 `eqFloat#` b1)- `andI#` (a2 `eqFloat#` b2)- `andI#` (a3 `eqFloat#` b3)- `andI#` (a4 `eqFloat#` b4)- )- {-# INLINE (==) #-}-- FloatX4# a1 a2 a3 a4 /= FloatX4# b1 b2 b3 b4 =- isTrue#- ( (a1 `neFloat#` b1)- `orI#` (a2 `neFloat#` b2)- `orI#` (a3 `neFloat#` b3)- `orI#` (a4 `neFloat#` b4)- )- {-# INLINE (/=) #-}------ | Implement partial ordering for `>`, `<`, `>=`, `<=`--- and lexicographical ordering for `compare`-instance Ord FloatX4 where- FloatX4# a1 a2 a3 a4 > FloatX4# b1 b2 b3 b4 =- isTrue#- ( (a1 `gtFloat#` b1)- `andI#` (a2 `gtFloat#` b2)- `andI#` (a3 `gtFloat#` b3)- `andI#` (a4 `gtFloat#` b4)- )- {-# INLINE (>) #-}-- FloatX4# a1 a2 a3 a4 < FloatX4# b1 b2 b3 b4 =- isTrue#- ( (a1 `ltFloat#` b1)- `andI#` (a2 `ltFloat#` b2)- `andI#` (a3 `ltFloat#` b3)- `andI#` (a4 `ltFloat#` b4)- )- {-# INLINE (<) #-}-- FloatX4# a1 a2 a3 a4 >= FloatX4# b1 b2 b3 b4 =- isTrue#- ( (a1 `geFloat#` b1)- `andI#` (a2 `geFloat#` b2)- `andI#` (a3 `geFloat#` b3)- `andI#` (a4 `geFloat#` b4)- )- {-# INLINE (>=) #-}-- FloatX4# a1 a2 a3 a4 <= FloatX4# b1 b2 b3 b4 =- isTrue#- ( (a1 `leFloat#` b1)- `andI#` (a2 `leFloat#` b2)- `andI#` (a3 `leFloat#` b3)- `andI#` (a4 `leFloat#` b4)- )- {-# INLINE (<=) #-}-- -- | Compare lexicographically- compare (FloatX4# a1 a2 a3 a4) (FloatX4# b1 b2 b3 b4)- | isTrue# (a1 `gtFloat#` b1) = GT- | isTrue# (a1 `ltFloat#` b1) = LT- | isTrue# (a2 `gtFloat#` b2) = GT- | isTrue# (a2 `ltFloat#` b2) = LT- | isTrue# (a3 `gtFloat#` b3) = GT- | isTrue# (a3 `ltFloat#` b3) = LT- | isTrue# (a4 `gtFloat#` b4) = GT- | isTrue# (a4 `ltFloat#` b4) = LT- | otherwise = EQ- {-# INLINE compare #-}-- -- | Element-wise minimum- min (FloatX4# a1 a2 a3 a4) (FloatX4# b1 b2 b3 b4) = FloatX4#- (if isTrue# (a1 `gtFloat#` b1) then b1 else a1)- (if isTrue# (a2 `gtFloat#` b2) then b2 else a2)- (if isTrue# (a3 `gtFloat#` b3) then b3 else a3)- (if isTrue# (a4 `gtFloat#` b4) then b4 else a4)- {-# INLINE min #-}-- -- | Element-wise maximum- max (FloatX4# a1 a2 a3 a4) (FloatX4# b1 b2 b3 b4) = FloatX4#- (if isTrue# (a1 `gtFloat#` b1) then a1 else b1)- (if isTrue# (a2 `gtFloat#` b2) then a2 else b2)- (if isTrue# (a3 `gtFloat#` b3) then a3 else b3)- (if isTrue# (a4 `gtFloat#` b4) then a4 else b4)- {-# INLINE max #-}------ | element-wise operations for vectors-instance Num FloatX4 where-- FloatX4# a1 a2 a3 a4 + FloatX4# b1 b2 b3 b4- = FloatX4# (plusFloat# a1 b1) (plusFloat# a2 b2) (plusFloat# a3 b3) (plusFloat# a4 b4)- {-# INLINE (+) #-}-- FloatX4# a1 a2 a3 a4 - FloatX4# b1 b2 b3 b4- = FloatX4# (minusFloat# a1 b1) (minusFloat# a2 b2) (minusFloat# a3 b3) (minusFloat# a4 b4)- {-# INLINE (-) #-}-- FloatX4# a1 a2 a3 a4 * FloatX4# b1 b2 b3 b4- = FloatX4# (timesFloat# a1 b1) (timesFloat# a2 b2) (timesFloat# a3 b3) (timesFloat# a4 b4)- {-# INLINE (*) #-}-- negate (FloatX4# a1 a2 a3 a4) = FloatX4#- (negateFloat# a1) (negateFloat# a2) (negateFloat# a3) (negateFloat# a4)- {-# INLINE negate #-}-- abs (FloatX4# a1 a2 a3 a4)- = FloatX4#- (if isTrue# (a1 `geFloat#` 0.0#) then a1 else negateFloat# a1)- (if isTrue# (a2 `geFloat#` 0.0#) then a2 else negateFloat# a2)- (if isTrue# (a3 `geFloat#` 0.0#) then a3 else negateFloat# a3)- (if isTrue# (a4 `geFloat#` 0.0#) then a4 else negateFloat# a4)- {-# INLINE abs #-}-- signum (FloatX4# a1 a2 a3 a4)- = FloatX4# (if isTrue# (a1 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a1 `ltFloat#` 0.0#) then -1.0# else 0.0# )- (if isTrue# (a2 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a2 `ltFloat#` 0.0#) then -1.0# else 0.0# )- (if isTrue# (a3 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a3 `ltFloat#` 0.0#) then -1.0# else 0.0# )- (if isTrue# (a4 `gtFloat#` 0.0#)- then 1.0#- else if isTrue# (a4 `ltFloat#` 0.0#) then -1.0# else 0.0# )- {-# INLINE signum #-}-- fromInteger n = case fromInteger n of F# x -> FloatX4# x x x x- {-# INLINE fromInteger #-}----instance Fractional FloatX4 where-- FloatX4# a1 a2 a3 a4 / FloatX4# b1 b2 b3 b4 = FloatX4#- (divideFloat# a1 b1) (divideFloat# a2 b2) (divideFloat# a3 b3) (divideFloat# a4 b4)- {-# INLINE (/) #-}-- recip (FloatX4# a1 a2 a3 a4) = FloatX4#- (divideFloat# 1.0# a1) (divideFloat# 1.0# a2) (divideFloat# 1.0# a3) (divideFloat# 1.0# a4)- {-# INLINE recip #-}-- fromRational r = case fromRational r of F# x -> FloatX4# x x x x- {-# INLINE fromRational #-}----instance Floating FloatX4 where-- pi = FloatX4#- 3.141592653589793238#- 3.141592653589793238#- 3.141592653589793238#- 3.141592653589793238#- {-# INLINE pi #-}-- exp (FloatX4# a1 a2 a3 a4) = FloatX4#- (expFloat# a1) (expFloat# a2) (expFloat# a3) (expFloat# a4)- {-# INLINE exp #-}-- log (FloatX4# a1 a2 a3 a4) = FloatX4#- (logFloat# a1) (logFloat# a2) (logFloat# a3) (logFloat# a4)- {-# INLINE log #-}-- sqrt (FloatX4# a1 a2 a3 a4) = FloatX4#- (sqrtFloat# a1) (sqrtFloat# a2) (sqrtFloat# a3) (sqrtFloat# a4)- {-# INLINE sqrt #-}-- sin (FloatX4# a1 a2 a3 a4) = FloatX4#- (sinFloat# a1) (sinFloat# a2) (sinFloat# a3) (sinFloat# a4)- {-# INLINE sin #-}-- cos (FloatX4# a1 a2 a3 a4) = FloatX4#- (cosFloat# a1) (cosFloat# a2) (cosFloat# a3) (cosFloat# a4)- {-# INLINE cos #-}-- tan (FloatX4# a1 a2 a3 a4) = FloatX4#- (tanFloat# a1) (tanFloat# a2) (tanFloat# a3) (tanFloat# a4)- {-# INLINE tan #-}-- asin (FloatX4# a1 a2 a3 a4) = FloatX4#- (asinFloat# a1) (asinFloat# a2) (asinFloat# a3) (asinFloat# a4)- {-# INLINE asin #-}-- acos (FloatX4# a1 a2 a3 a4) = FloatX4#- (acosFloat# a1) (acosFloat# a2) (acosFloat# a3) (acosFloat# a4)- {-# INLINE acos #-}-- atan (FloatX4# a1 a2 a3 a4) = FloatX4#- (atanFloat# a1) (atanFloat# a2) (atanFloat# a3) (atanFloat# a4)- {-# INLINE atan #-}-- sinh (FloatX4# a1 a2 a3 a4) = FloatX4#- (sinhFloat# a1) (sinhFloat# a2) (sinhFloat# a3) (sinhFloat# a4)- {-# INLINE sinh #-}-- cosh (FloatX4# a1 a2 a3 a4) = FloatX4#- (coshFloat# a1) (coshFloat# a2) (coshFloat# a3) (coshFloat# a4)- {-# INLINE cosh #-}-- tanh (FloatX4# a1 a2 a3 a4) = FloatX4#- (tanhFloat# a1) (tanhFloat# a2) (tanhFloat# a3) (tanhFloat# a4)- {-# INLINE tanh #-}-- FloatX4# a1 a2 a3 a4 ** FloatX4# b1 b2 b3 b4 = FloatX4#- (powerFloat# a1 b1) (powerFloat# a2 b2) (powerFloat# a3 b3) (powerFloat# a4 b4)- {-# INLINE (**) #-}-- logBase x y = log y / log x- {-# INLINE logBase #-}-- asinh x = log (x + sqrt (1.0+x*x))- {-# INLINE asinh #-}-- acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))- {-# INLINE acosh #-}-- atanh x = 0.5 * log ((1.0+x) / (1.0-x))- {-# INLINE atanh #-}---- offset in bytes is S times bigger than offset in prim elements,--- when S is power of two, this is equal to shift-#define BOFF_TO_PRIMOFF(off) uncheckedIShiftRL# off 2#-#define ELEM_N 4--instance PrimBytes FloatX4 where-- getBytes (FloatX4# a1 a2 a3 a4) = case runRW#- ( \s0 -> case newByteArray# (byteSize @FloatX4 undefined) s0 of- (# s1, marr #) -> case writeFloatArray# marr 0# a1 s1 of- s2 -> case writeFloatArray# marr 1# a2 s2 of- s3 -> case writeFloatArray# marr 2# a3 s3 of- s4 -> case writeFloatArray# marr 3# a4 s4 of- s5 -> unsafeFreezeByteArray# marr s5- ) of (# _, a #) -> a- {-# INLINE getBytes #-}-- fromBytes off arr- | i <- BOFF_TO_PRIMOFF(off)- = FloatX4#- (indexFloatArray# arr i)- (indexFloatArray# arr (i +# 1#))- (indexFloatArray# arr (i +# 2#))- (indexFloatArray# arr (i +# 3#))- {-# INLINE fromBytes #-}-- readBytes mba off s0- | i <- BOFF_TO_PRIMOFF(off)- = case readFloatArray# mba i s0 of- (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> case readFloatArray# mba (i +# 3#) s3 of- (# s4, a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)- {-# INLINE readBytes #-}-- writeBytes mba off (FloatX4# a1 a2 a3 a4) s- | i <- BOFF_TO_PRIMOFF(off)- = writeFloatArray# mba (i +# 3#) a4- ( writeFloatArray# mba (i +# 2#) a3- ( writeFloatArray# mba (i +# 1#) a2- ( writeFloatArray# mba i a1 s )))- {-# INLINE writeBytes #-}-- readAddr addr s0- = case readFloatOffAddr# addr 0# s0 of- (# s1, a1 #) -> case readFloatOffAddr# addr 1# s1 of- (# s2, a2 #) -> case readFloatOffAddr# addr 2# s2 of- (# s3, a3 #) -> case readFloatOffAddr# addr 3# s3 of- (# s4, a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)- {-# INLINE readAddr #-}-- writeAddr (FloatX4# a1 a2 a3 a4) addr s- = writeFloatOffAddr# addr 3# a4- ( writeFloatOffAddr# addr 2# a3- ( writeFloatOffAddr# addr 1# a2- ( writeFloatOffAddr# addr 0# a1 s )))- {-# INLINE writeAddr #-}-- byteSize _ = byteSize @Float undefined *# ELEM_N#- {-# INLINE byteSize #-}-- byteAlign _ = byteAlign @Float undefined- {-# INLINE byteAlign #-}-- byteOffset _ = 0#- {-# INLINE byteOffset #-}-- indexArray ba off- | i <- off *# ELEM_N#- = FloatX4#- (indexFloatArray# ba i)- (indexFloatArray# ba (i +# 1#))- (indexFloatArray# ba (i +# 2#))- (indexFloatArray# ba (i +# 3#))- {-# INLINE indexArray #-}-- readArray mba off s0- | i <- off *# ELEM_N#- = case readFloatArray# mba i s0 of- (# s1, a1 #) -> case readFloatArray# mba (i +# 1#) s1 of- (# s2, a2 #) -> case readFloatArray# mba (i +# 2#) s2 of- (# s3, a3 #) -> case readFloatArray# mba (i +# 3#) s3 of- (# s4, a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)- {-# INLINE readArray #-}-- writeArray mba off (FloatX4# a1 a2 a3 a4) s- | i <- off *# ELEM_N#- = writeFloatArray# mba (i +# 3#) a4- ( writeFloatArray# mba (i +# 2#) a3- ( writeFloatArray# mba (i +# 1#) a2- ( writeFloatArray# mba i a1 s )))- {-# INLINE writeArray #-}---instance PrimArray Float FloatX4 where-- broadcast (F# x) = FloatX4# x x x x- {-# INLINE broadcast #-}-- ix# 0# (FloatX4# a1 _ _ _) = F# a1- ix# 1# (FloatX4# _ a2 _ _) = F# a2- ix# 2# (FloatX4# _ _ a3 _) = F# a3- ix# 3# (FloatX4# _ _ _ a4) = F# a4- ix# _ _ = undefined- {-# INLINE ix# #-}-- gen# _ f s0 = case f s0 of- (# s1, F# a1 #) -> case f s1 of- (# s2, F# a2 #) -> case f s2 of- (# s3, F# a3 #) -> case f s3 of- (# s4, F# a4 #) -> (# s4, FloatX4# a1 a2 a3 a4 #)--- upd# _ 0# (F# q) (FloatX4# _ y z w) = FloatX4# q y z w- upd# _ 1# (F# q) (FloatX4# x _ z w) = FloatX4# x q z w- upd# _ 2# (F# q) (FloatX4# x y _ w) = FloatX4# x y q w- upd# _ 3# (F# q) (FloatX4# x y z _) = FloatX4# x y z q- upd# _ _ _ x = x- {-# INLINE upd# #-}-- elemOffset _ = 0#- {-# INLINE elemOffset #-}-- elemSize0 _ = ELEM_N#- {-# INLINE elemSize0 #-}-- fromElems off _ ba = FloatX4#- (indexFloatArray# ba off)- (indexFloatArray# ba (off +# 1#))- (indexFloatArray# ba (off +# 2#))- (indexFloatArray# ba (off +# 3#))- {-# INLINE fromElems #-}-------------------------------------------------------------------------------------- Rewrite rules to improve efficiency of algorithms------ Here we don't have access to DataFrame constructors, because we cannot import--- Numeric.DataFrame.Type module.--- However, we know that all DataFrame instances are just newtype wrappers--- (as well as Scalar). Thus, we can use unsafeCoerce# to get access to Arrays--- inside DataFrames.--------------------------------------------------------------------------------------getIdxOffset :: Idxs '[4] -> Int#-getIdxOffset is = case unsafeCoerce# is of- [W# i] -> word2Int# i -# 1#- _ -> 0#-{-# INLINE getIdxOffset #-}---{-# RULES-"index/FloatX4" forall i . (!.) @Float @'[] i- = unsafeCoerce# (ix# @Float @FloatX4 (getIdxOffset i))-- #-}
− src/Numeric/DataFrame/Internal/Array/Family/ScalarBase.hs
@@ -1,51 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE UnboxedTuples #-}-module Numeric.DataFrame.Internal.Array.Family.ScalarBase (ScalarBase (..)) where---import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.PrimBytes---- | Specialize ScalarBase type without any arrays-newtype ScalarBase t = ScalarBase { _unScalarBase :: t }- deriving ( Enum, Eq, Integral- , Num, Fractional, Floating, Ord, Read, Real, RealFrac, RealFloat- , PrimBytes)--instance Show t => Show (ScalarBase t) where- show (ScalarBase t) = "{ " ++ show t ++ " }"--deriving instance {-# OVERLAPPABLE #-} Bounded t => Bounded (ScalarBase t)-instance {-# OVERLAPPING #-} Bounded (ScalarBase Double) where- maxBound = ScalarBase inftyD- minBound = ScalarBase $ negate inftyD-instance {-# OVERLAPPING #-} Bounded (ScalarBase Float) where- maxBound = ScalarBase inftyF- minBound = ScalarBase $ negate inftyF--instance PrimBytes t => PrimArray t (ScalarBase t) where- broadcast = unsafeCoerce#- {-# INLINE broadcast #-}- ix# _ = unsafeCoerce#- {-# INLINE ix# #-}- gen# _ = unsafeCoerce#- {-# INLINE gen# #-}- upd# _ 0# = const . ScalarBase- upd# _ _ = const id- {-# INLINE upd# #-}- elemOffset _ = 0#- {-# INLINE elemOffset #-}- elemSize0 _ = 1#- {-# INLINE elemSize0 #-}- fromElems off _ ba = indexArray ba off- {-# INLINE fromElems #-}--_suppressHlintUnboxedTuplesWarning :: () -> (# (), () #)-_suppressHlintUnboxedTuplesWarning = undefined
− src/Numeric/DataFrame/Internal/Array/PrimOps.hs
@@ -1,94 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE UnboxedTuples #-}--- | Internal primitive functions shared across modules-module Numeric.DataFrame.Internal.Array.PrimOps where--import GHC.Base-import Numeric.Dimensions--inftyD :: Double-inftyD = read "Infinity"-{-# INLINE inftyD #-}--inftyF :: Float-inftyF = read "Infinity"-{-# INLINE inftyF #-}----minInt# :: Int# -> Int# -> Int#-minInt# a b | isTrue# (a ># b) = b- | otherwise = a-{-# INLINE minInt# #-}---loop# :: Int# -- ^ initial value- -> Int# -- ^ step- -> Int# -- ^ final value (LESS THAN condition)- -> (Int# -> State# s -> State# s) -> State# s -> State# s-loop# n0 di n1 f = loop0 n0- where- loop0 i s | isTrue# (i >=# n1) = s- | otherwise = loop0 (i +# di) (f i s)-{-# INLINE loop# #-}----- | Loop with given increment, plus keep the step number--- in the first argument of the iterated function-loopWithI# :: Int# -- ^ initial value- -> Int# -- ^ step- -> Int# -- ^ final value (LESS THAN condition)- -> (Int# -> Int# -> State# s -> State# s) -> State# s -> State# s-loopWithI# n0 di n1 f = loop0 0# n0- where- loop0 j i s | isTrue# (i >=# n1) = s- | otherwise = loop0 (j +# 1#) (i +# di) (f j i s)-{-# INLINE loopWithI# #-}----- | Do something in a loop for int i from 0 to (n-1)-loop1# :: Int# -> (Int# -> State# s -> State# s) -> State# s -> State# s-loop1# n f = loop0 0#- where- loop0 i s | isTrue# (i ==# n) = s- | otherwise = loop0 (i +# 1#) (f i s)-{-# INLINE loop1# #-}---- | Do something in a loop for int i from 0 to (n-1)-loop1a# :: Int# -> (Int# -> a -> a) -> a -> a-loop1a# n f = loop0 0#- where- loop0 i s | isTrue# (i ==# n) = s- | otherwise = s `seq` case f i s of s1 -> s1 `seq` loop0 (i +# 1#) s1-{-# INLINE loop1a# #-}----- | Same as overDim#, but with no return value-overDim_# :: Dims (ds :: [k])- -> (Idxs ds -> Int# -> State# s -> State# s) -- ^ function to map over each dimension- -> Int# -- ^ Initial offset- -> Int# -- ^ offset step- -> State# s- -> State# s-overDim_# ds f off0# step# s0 = case overDim_'# ds g off0# s0 of- (# s1, _ #) -> s1- where- g i off# s = (# f i off# s, off# +# step# #)-{-# INLINE overDim_# #-}---overDim_'# :: Dims (ds :: [k])- -> (Idxs ds -> Int# -> State# s -> (# State# s, Int# #)) -- ^ function to map over each dimension- -> Int# -- ^ Initial offset- -> State# s- -> (# State# s, Int# #)-overDim_'# U f = f U-overDim_'# (d :* ds) f = overDim_'# ds (loop 1)- where- n = dimVal d- loop i js off# s | i > n = (# s , off# #)- | otherwise = case f (Idx i :* js) off# s of- (# s', off1# #) -> loop (i+1) js off1# s'
+ src/Numeric/DataFrame/Internal/Backend.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)+{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}+#else+{-# OPTIONS_GHC -fplugin Data.Constraint.Deriving #-}+#endif++module Numeric.DataFrame.Internal.Backend+ ( DFBackend, Backend (..), BackendFamily, KnownBackend ()+ , inferKnownBackend, inferPrimElem+ -- * Auto-deriving instances+ , inferEq, inferOrd+ , inferProductOrder, inferPONonTransitive, inferPOPartial+ , inferBounded, inferNum+ , inferFractional, inferFloating+ , inferPrimBytes, inferPrimArray+ ) where+++import Data.Constraint+import Data.Constraint.Deriving+import Data.Constraint.Unsafe+import Data.Kind (Type)+import Unsafe.Coerce (unsafeCoerce)++import Numeric.DataFrame.Internal.PrimArray+import Numeric.Dimensions+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial++import Numeric.DataFrame.Internal.Backend.Family (BackendFamily)+import qualified Numeric.DataFrame.Internal.Backend.Family as Impl (KnownBackend,+ inferBackendInstance,+ inferKnownBackend,+ inferPrimArray,+ inferPrimElem)+import Numeric.DataFrame.Internal.BackendI (I)++-- | Implementation behind the DataFrame+type DFBackend (t :: Type) (ds :: [Nat]) = Backend I t ds (BackendFamily t ds)++-- | Backend resolver:+-- Use this constraint to find any class instances defined for all DataFrame implementations,+-- e.g. @Num@, @PrimBytes@, etc.+type KnownBackend (t :: Type) (ds :: [Nat]) = Impl.KnownBackend t ds (BackendFamily t ds)++-- | A newtype wrapper for all DataFrame implementations.+-- I need two layers of wrappers to provide default overlappable instances to+-- all type classes using KnownBackend mechanics.+-- Type arguments are redundant here;+-- nevertheless, they improve readability of error messages.+newtype Backend (i :: Type) (t :: Type) (ds :: [Nat]) (backend :: Type)+ = Backend { _getBackend :: backend }+type role Backend phantom phantom phantom representational+type instance DeriveContext (Backend I t ds b) = b ~ BackendFamily t ds+-- When typechecker knows what the third parameter @b@ is, no instances overlap,+-- because @b@ is always always a concrete type.+-- The "dynamic instances" derived via ToInstance have to be incoherent,+-- because @BackendFamily t ds@ as a type family (before resolving it)+-- is no more conrete than just @b@.+{-# ANN type Backend (DeriveAll' NoOverlap ["KnownBackend"]) #-}++++inferKnownBackend+ :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions ds)+ => Dict (KnownBackend t ds)+inferKnownBackend+ = Impl.inferKnownBackend @t @ds @(BackendFamily t ds)++inferPrimElem+ :: forall (t :: Type) (d :: Nat) (ds :: [Nat])+ . KnownBackend t (d ': ds)+ => DFBackend t (d ': ds) -> Dict (PrimBytes t)+inferPrimElem = Impl.inferPrimElem @t @d @ds . _getBackend++++inferEq+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Eq t, Impl.KnownBackend t ds b)+ => Dict (Eq (Backend I t ds b))+inferEq+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferOrd+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (Backend I t ds b))+inferOrd+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferProductOrder+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (ProductOrder (Backend I t ds b))+inferProductOrder+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferPONonTransitive+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (NonTransitive.ProductOrd (Backend I t ds b)))+inferPONonTransitive+ = mapDict (unsafeDerive NonTransitive.ProductOrd)+ . mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferPOPartial+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (Partial.ProductOrd (Backend I t ds b)))+inferPOPartial+ = mapDict (unsafeDerive Partial.ProductOrd)+ . mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferBounded+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Bounded t, Impl.KnownBackend t ds b)+ => Dict (Bounded (Backend I t ds b))+inferBounded+ -- Here is an ugly trick:+ -- We don't have instance of @Bounded Float@ and @Bounded Double@.+ -- However, we want to have an instance @Bounded t => Bounded (Backend t ds b)@.+ -- Some specialized implementations (e.g. FloatX4) require explicit+ -- constraints @Bounded Float@ or @Bounded Double@.+ -- To satisfy these, I pull @Bounded t@ convincing the compiler that @t ~ Float@.+ -- This should work fine even if a user implements instances of Bounded for+ -- the floating types, because we know that @t ~ Float@ or @t ~ Double@+ -- automatically whenever this instance is called for these types.+ | Dict <- (case (unsafeCoerce (Dict @(t ~ t)) :: Dict (t ~ Float)) of+ Dict -> Dict) :: Dict (Bounded Float)+ , Dict <- (case (unsafeCoerce (Dict @(t ~ t)) :: Dict (t ~ Double)) of+ Dict -> Dict) :: Dict (Bounded Double)+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferNum+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Num t, Impl.KnownBackend t ds b)+ => Dict (Num (Backend I t ds b))+inferNum+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferFractional+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Fractional t, Impl.KnownBackend t ds b)+ => Dict (Fractional (Backend I t ds b))+inferFractional+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferFloating+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Floating t, Impl.KnownBackend t ds b)+ => Dict (Floating (Backend I t ds b))+inferFloating+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined+++inferPrimBytes+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, Dimensions ds, Impl.KnownBackend t ds b)+ => Dict (PrimBytes (Backend I t ds b))+inferPrimBytes+ = mapDict toBackend+ . mapDict (Sub (Impl.inferBackendInstance @t @ds))+ $ inferDeriveContext @t @ds @b undefined++inferPrimArray+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, Impl.KnownBackend t ds b)+ => Dict (PrimArray t (Backend I t ds b))+inferPrimArray+ = mapDict toBackend+ . mapDict (Sub (Impl.inferPrimArray @t @ds))+ $ inferDeriveContext @t @ds @b undefined+++-- This is the rule that cannot be encoded in the type system, but enforced+-- as an invariant: Backend t ds b implies DeriveContext t ds b+inferDeriveContext :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . Backend I t ds b+ -> Dict (DeriveContext (Backend I t ds b))+inferDeriveContext _ = unsafeCoerce (Dict :: Dict (b ~ b))+{-# INLINE inferDeriveContext #-}++-- Backend is the newtype wrapper over b.+-- It has the same represenation and I expect it to have the same instance behavior.+toBackend :: forall c t ds b . c b :- c (Backend I t ds b)+toBackend = unsafeDerive Backend+{-# INLINE toBackend #-}
+ src/Numeric/DataFrame/Internal/Backend.hs-boot view
@@ -0,0 +1,117 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE TypeOperators #-}+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)+{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}+#endif++module Numeric.DataFrame.Internal.Backend+ ( DFBackend, Backend (..), BackendFamily, KnownBackend ()+ , inferKnownBackend, inferPrimElem+ -- * Auto-deriving instances+ , inferEq, inferOrd+ , inferProductOrder, inferPONonTransitive, inferPOPartial+ , inferBounded, inferNum+ , inferFractional, inferFloating+ , inferPrimBytes, inferPrimArray+ ) where++import Data.Kind (Type)+import Numeric.DataFrame.Internal.PrimArray (PrimArray)+import Numeric.Dimensions (Dict, Dimensions, Nat)+import Numeric.PrimBytes (PrimBytes)+import Numeric.ProductOrd (ProductOrder)+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial++import {-# SOURCE #-} Numeric.DataFrame.Internal.Backend.Family (BackendFamily)+import {-# SOURCE #-} qualified Numeric.DataFrame.Internal.Backend.Family as Impl+ (KnownBackend)+import {-# SOURCE #-} Numeric.DataFrame.Internal.BackendI (I)++-- | Implementation behind the DataFrame+type DFBackend (t :: Type) (ds :: [Nat]) = Backend I t ds (BackendFamily t ds)++-- | Backend resolver:+-- Use this constraint to find any class instances defined for all DataFrame implementations,+-- e.g. @Num@, @PrimBytes@, etc.+type KnownBackend (t :: Type) (ds :: [Nat]) = Impl.KnownBackend t ds (BackendFamily t ds)++-- | A newtype wrapper for all DataFrame implementations.+-- I need two layers of wrappers to provide default overlappable instances to+-- all type classes using KnownBackend mechanics.+-- Type arguments are redundant here;+-- nevertheless, they improve readability of error messages.+newtype Backend (i :: Type) (t :: Type) (ds :: [Nat]) (backend :: Type)+ = Backend { _getBackend :: backend }+type role Backend phantom phantom phantom representational++inferKnownBackend+ :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions ds)+ => Dict (KnownBackend t ds)++inferPrimElem+ :: forall (t :: Type) (d :: Nat) (ds :: [Nat])+ . KnownBackend t (d ': ds)+ => DFBackend t (d ': ds) -> Dict (PrimBytes t)++inferEq+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Eq t, Impl.KnownBackend t ds b)+ => Dict (Eq (Backend I t ds b))++inferOrd+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (Backend I t ds b))++inferProductOrder+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (ProductOrder (Backend I t ds b))++inferPONonTransitive+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (NonTransitive.ProductOrd (Backend I t ds b)))++inferPOPartial+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (Partial.ProductOrd (Backend I t ds b)))++inferBounded+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Bounded t, Impl.KnownBackend t ds b)+ => Dict (Bounded (Backend I t ds b))++inferNum+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Num t, Impl.KnownBackend t ds b)+ => Dict (Num (Backend I t ds b))++inferFractional+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Fractional t, Impl.KnownBackend t ds b)+ => Dict (Fractional (Backend I t ds b))++inferFloating+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Floating t, Impl.KnownBackend t ds b)+ => Dict (Floating (Backend I t ds b))++inferPrimBytes+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, Dimensions ds, Impl.KnownBackend t ds b)+ => Dict (PrimBytes (Backend I t ds b))++inferPrimArray+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, Impl.KnownBackend t ds b)+ => Dict (PrimArray t (Backend I t ds b))
+ src/Numeric/DataFrame/Internal/BackendI.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fdefer-type-errors #-}+{-# OPTIONS_GHC -fno-warn-deferred-type-errors #-}+{-# OPTIONS_GHC -fno-warn-missing-methods #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}+#else+{-# OPTIONS_GHC -fplugin Data.Constraint.Deriving #-}+#endif++module Numeric.DataFrame.Internal.BackendI+ ( I+ , inferEq, inferOrd+ , inferProductOrder, inferPONonTransitive, inferPOPartial+ , inferBounded, inferNum+ , inferFractional, inferFloating+ , inferPrimBytes, inferPrimArray+ ) where++++import Data.Constraint.Deriving (OverlapMode (..),+ ToInstance (..))+import Data.Kind (Type)+import Numeric.DataFrame.Internal.PrimArray (PrimArray)+import Numeric.Dimensions (Dict, Dimensions, Nat)+import Numeric.PrimBytes (PrimBytes)+import Numeric.ProductOrd (ProductOrder)+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial++import {-# SOURCE #-} Numeric.DataFrame.Internal.Backend (Backend)+import {-# SOURCE #-} qualified Numeric.DataFrame.Internal.Backend as Backend+import {-# SOURCE #-} qualified Numeric.DataFrame.Internal.Backend.Family as Impl++++{- | The instance keeper for the `Backend` type.++ Using this data as a tag to the `Backend` type allows to define `Backend` instances+ in two different modules without any orphans.++ -}+data I+++{-# ANN inferEq (ToInstance Incoherent) #-}+inferEq+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Eq t, Impl.KnownBackend t ds b)+ => Dict (Eq (Backend I t ds b))+inferEq = Backend.inferEq @t @ds @b++{-# ANN inferOrd (ToInstance Incoherent) #-}+inferOrd+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (Backend I t ds b))+inferOrd = Backend.inferOrd @t @ds @b++{-# ANN inferProductOrder (ToInstance Incoherent) #-}+inferProductOrder+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (ProductOrder (Backend I t ds b))+inferProductOrder = Backend.inferProductOrder @t @ds @b++{-# ANN inferPONonTransitive (ToInstance Incoherent) #-}+inferPONonTransitive+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (NonTransitive.ProductOrd (Backend I t ds b)))+inferPONonTransitive = Backend.inferPONonTransitive @t @ds @b++{-# ANN inferPOPartial (ToInstance Incoherent) #-}+inferPOPartial+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Dict (Ord (Partial.ProductOrd (Backend I t ds b)))+inferPOPartial = Backend.inferPOPartial @t @ds @b++{-# ANN inferBounded (ToInstance Incoherent) #-}+inferBounded+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Bounded t, Impl.KnownBackend t ds b)+ => Dict (Bounded (Backend I t ds b))+inferBounded = Backend.inferBounded @t @ds @b++{-# ANN inferNum (ToInstance Incoherent) #-}+inferNum+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Num t, Impl.KnownBackend t ds b)+ => Dict (Num (Backend I t ds b))+inferNum = Backend.inferNum @t @ds @b++{-# ANN inferFractional (ToInstance Incoherent) #-}+inferFractional+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Fractional t, Impl.KnownBackend t ds b)+ => Dict (Fractional (Backend I t ds b))+inferFractional = Backend.inferFractional @t @ds @b++{-# ANN inferFloating (ToInstance Incoherent) #-}+inferFloating+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Floating t, Impl.KnownBackend t ds b)+ => Dict (Floating (Backend I t ds b))+inferFloating = Backend.inferFloating @t @ds @b++{-# ANN inferPrimBytes (ToInstance Incoherent) #-}+inferPrimBytes+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, Dimensions ds, Impl.KnownBackend t ds b)+ => Dict (PrimBytes (Backend I t ds b))+inferPrimBytes = Backend.inferPrimBytes @t @ds @b++{-# ANN inferPrimArray (ToInstance Incoherent) #-}+inferPrimArray+ :: forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (PrimBytes t, Impl.KnownBackend t ds b)+ => Dict (PrimArray t (Backend I t ds b))+inferPrimArray = Backend.inferPrimArray @t @ds @b++++-- The instances below are bumb stubs needed only to compile haddock+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Eq t, Impl.KnownBackend t ds b)+ => Eq (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Ord (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => ProductOrder (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Ord (NonTransitive.ProductOrd (Backend I t ds b))++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Ord t, Impl.KnownBackend t ds b)+ => Ord (Partial.ProductOrd (Backend I t ds b))++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Bounded t, Impl.KnownBackend t ds b)+ => Bounded (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Num t, Impl.KnownBackend t ds b)+ => Num (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Fractional t, Impl.KnownBackend t ds b)+ => Fractional (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . (Floating t, Impl.KnownBackend t ds b)+ => Floating (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . ( PrimBytes t+ , Dimensions ds+ , Impl.KnownBackend t ds b+ )+ => PrimBytes (Backend I t ds b)++instance+ forall (t :: Type) (ds :: [Nat]) (b :: Type)+ . ( PrimBytes t+ , Impl.KnownBackend t ds b+ )+ => PrimArray t (Backend I t ds b)++#endif
+ src/Numeric/DataFrame/Internal/BackendI.hs-boot view
@@ -0,0 +1,9 @@+module Numeric.DataFrame.Internal.BackendI (I) where++{- | The instance keeper for the `Backend` type.++ Using this data as a tag to the `Backend` type allows to define `Backend` instances+ in two different modules without any orphans.++ -}+data I
src/Numeric/DataFrame/Internal/Mutable.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-}@@ -11,6 +10,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-} ----------------------------------------------------------------------------- -- | -- Module : Numeric.DataFrame.Internal.Mutable@@ -27,6 +27,7 @@ ( MDataFrame () , newDataFrame#, newPinnedDataFrame# , copyDataFrame#, copyMDataFrame#+ , copyDataFrame'#, copyMDataFrame'# , freezeDataFrame#, unsafeFreezeDataFrame# , thawDataFrame#, thawPinDataFrame#, unsafeThawDataFrame# , writeDataFrame#, writeDataFrameOff#@@ -35,17 +36,17 @@ ) where -import GHC.Base-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Type-import Numeric.Dimensions-import Numeric.PrimBytes+import GHC.Base+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.Type+import Numeric.Dimensions+import Numeric.PrimBytes -- | Mutable DataFrame type. -- Keeps element offset, number of elements, and a mutable byte storage data MDataFrame s t (ns :: [Nat])- = MDataFrame# Int# Int# (MutableByteArray# s)+ = MDataFrame# Int# CumulDims (MutableByteArray# s) -- | Create a new mutable DataFrame.@@ -53,10 +54,10 @@ . ( PrimBytes t, Dimensions ns) => State# s -> (# State# s, MDataFrame s t ns #) newDataFrame# s0- | W# nw <- totalDim' @ns- , n <- word2Int# nw+ | steps <- cumulDims $ dims @ns+ , n <- cdTotalDim# steps , (# s1, mba #) <- newByteArray# (n *# byteSize @t undefined) s0- = (# s1, MDataFrame# 0# n mba #)+ = (# s1, MDataFrame# 0# steps mba #) {-# INLINE newDataFrame# #-} -- | Create a new mutable DataFrame.@@ -64,109 +65,163 @@ . ( PrimBytes t, Dimensions ns) => State# s -> (# State# s, MDataFrame s t ns #) newPinnedDataFrame# s0- | W# nw <- totalDim' @ns- , n <- word2Int# nw+ | steps <- cumulDims $ dims @ns+ , n <- cdTotalDim# steps , (# s1, mba #) <- newAlignedPinnedByteArray# (n *# byteSize @t undefined) (byteAlign @t undefined) s0- = (# s1, MDataFrame# 0# n mba #)+ = (# s1, MDataFrame# 0# steps mba #) {-# INLINE newPinnedDataFrame# #-} -- | Copy one DataFrame into another mutable DataFrame at specified position.-copyDataFrame# :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat)- (bs :: [Nat]) (asbs :: [Nat]) s- . ( PrimBytes t- , PrimBytes (DataFrame t (as +: b'))+--+-- In contrast to @copyDataFrame'@, this function allows to copy over a range of contiguous+-- indices over a single dimension.+-- For example, you can write a 3x4 matrix into a 7x4 matrix, starting at indices 0..3.+copyDataFrame# :: forall (t :: Type)+ (b :: Nat) (bi :: Nat) (bd :: Nat)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( b ~ (bi + bd - 1)+ , PrimBytes t+ , PrimBytes (DataFrame t (bd :+ bs)) , ConcatList as (b :+ bs) asbs- , Dimensions (b :+ bs) )- => DataFrame t (as +: b') -> Idxs (b :+ bs) -> MDataFrame s t asbs+ => Idxs (as +: bi) -> DataFrame t (bd :+ bs) -> MDataFrame s t asbs -> State# s -> (# State# s, () #)-copyDataFrame# df ei (MDataFrame# off _ mba) s- | I# i <- fromEnum ei+copyDataFrame# ei df (MDataFrame# off steps mba) s+ | I# i <- cdIx steps ei = (# writeBytes mba ((off +# i) *# byteSize @t undefined) df s, () #) {-# INLINE copyDataFrame# #-} ++{-# ANN copyMDataFrame# "HLint: ignore Use camelCase" #-} -- | Copy one mutable DataFrame into another mutable DataFrame at specified position.-copyMDataFrame# :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat)- (bs :: [Nat]) (asbs :: [Nat]) s- . ( PrimBytes t+--+-- In contrast to @copyMDataFrame'@, this function allows to copy over a range of contiguous+-- indices over a single dimension.+-- For example, you can write a 3x4 matrix into a 7x4 matrix, starting at indices 0..3.+copyMDataFrame# :: forall (t :: Type)+ (b :: Nat) (bi :: Nat) (bd :: Nat)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( b ~ (bi + bd - 1)+ , PrimBytes t , ConcatList as (b :+ bs) asbs- , Dimensions (b :+ bs) )- => MDataFrame s t (as +: b') -> Idxs (b :+ bs) -> MDataFrame s t asbs+ => Idxs (as +: bi) -> MDataFrame s t (bd :+ bs) -> MDataFrame s t asbs -> State# s -> (# State# s, () #)-copyMDataFrame# (MDataFrame# offA lenA arrA) ei (MDataFrame# offM _ arrM) s+ -- all information for copying in this case is taken from the inside+ -- of the data types at the term level;+ -- steps zips with indices just fine independently of their types+ -- and length.+ -- Thus, it's fine here to just unsafeCoerce# an index.+copyMDataFrame# ei df =+ copyMDataFrame'#+ (unsafeCoerce# ei :: Idxs as)+ (unsafeCoerce# df :: MDataFrame s t (b :+ bs))+{-# INLINE copyMDataFrame# #-}++{-# ANN copyDataFrame'# "HLint: ignore Use camelCase" #-}+-- | Copy one DataFrame into another mutable DataFrame at specified position.+--+-- This is a simpler version of @copyDataFrame@ that allows to copy over one index at a time.+copyDataFrame'# :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( PrimBytes t+ , PrimBytes (DataFrame t bs)+ , ConcatList as bs asbs+ )+ => Idxs as -> DataFrame t bs -> MDataFrame s t asbs+ -> State# s -> (# State# s, () #)+copyDataFrame'# ei df (MDataFrame# off steps mba) s+ | I# i <- cdIx steps ei+ = (# writeBytes mba ((off +# i) *# byteSize @t undefined) df s, () #)+{-# INLINE copyDataFrame'# #-}++{-# ANN copyMDataFrame'# "HLint: ignore Use camelCase" #-}+-- | Copy one mutable DataFrame into another mutable DataFrame at specified position.+--+-- This is a simpler version of @copyMDataFrame@ that allows to copy over one index at a time.+copyMDataFrame'# :: forall (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( PrimBytes t+ , ConcatList as bs asbs+ )+ => Idxs as -> MDataFrame s t bs -> MDataFrame s t asbs+ -> State# s -> (# State# s, () #)+copyMDataFrame'# ei (MDataFrame# offA stepsA arrA) (MDataFrame# offM stepsM arrM) s | elS <- byteSize @t undefined- , I# i <- fromEnum ei+ , lenA <- cdTotalDim# stepsA+ , I# i <- cdIx stepsM ei = (# copyMutableByteArray# arrA (offA *# elS) arrM ((offM +# i) *# elS) (lenA *# elS) s , () #)-{-# INLINE copyMDataFrame# #-}+{-# INLINE copyMDataFrame'# #-} -- | Make a mutable DataFrame immutable, without copying. unsafeFreezeDataFrame# :: forall (t :: Type) (ns :: [Nat]) s . PrimArray t (DataFrame t ns) => MDataFrame s t ns -> State# s -> (# State# s, DataFrame t ns #)-unsafeFreezeDataFrame# (MDataFrame# offM lenM arrM) s1+unsafeFreezeDataFrame# (MDataFrame# offM steps arrM) s1 | (# s2, arrA #) <- unsafeFreezeByteArray# arrM s1- = (# s2, fromElems offM lenM arrA #)+ = (# s2, fromElems steps offM arrA #) {-# INLINE unsafeFreezeDataFrame# #-} -- | Copy content of a mutable DataFrame into a new immutable DataFrame. freezeDataFrame# :: forall (t :: Type) (ns :: [Nat]) s . PrimArray t (DataFrame t ns) => MDataFrame s t ns -> State# s -> (# State# s, DataFrame t ns #)-freezeDataFrame# (MDataFrame# offM n arrM) s0+freezeDataFrame# (MDataFrame# offM steps arrM) s0 | elS <- byteSize @t undefined+ , n <- cdTotalDim# steps , (# s1, mba #) <- newByteArray# (n *# elS) s0 , s2 <- copyMutableByteArray# arrM (offM *# elS) mba 0# (n *# elS) s1 , (# s3, arrA #) <- unsafeFreezeByteArray# mba s2- = (# s3, fromElems 0# n arrA #)+ = (# s3, fromElems steps 0# arrA #) {-# INLINE freezeDataFrame# #-} -- | Create a new mutable DataFrame and copy content of immutable one in there. thawDataFrame# :: forall (t :: Type) (ns :: [Nat]) s- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . ( Dimensions ns+ , PrimBytes (DataFrame t ns)) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #) thawDataFrame# df s0- | elS <- byteSize @t undefined- , arrA <- getBytes df- , boff <- byteOffset df+ | arrA <- getBytes df+ , boff <- byteOffset df , bsize <- byteSize df+ , steps <- cumulDims $ dims @ns , (# s1, arrM #) <- newByteArray# bsize s0 , s2 <- copyByteArray# arrA boff arrM 0# bsize s1- = (# s2, MDataFrame# 0# (quotInt# bsize elS) arrM #)+ = (# s2, MDataFrame# 0# steps arrM #) {-# INLINE thawDataFrame# #-} -- | Create a new mutable DataFrame and copy content of immutable one in there. -- The result array is pinned and aligned. thawPinDataFrame# :: forall (t :: Type) (ns :: [Nat]) s- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . ( Dimensions ns+ , PrimBytes (DataFrame t ns)) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #) thawPinDataFrame# df s0- | elS <- byteSize @t undefined- , arrA <- getBytes df- , boff <- byteOffset df+ | arrA <- getBytes df+ , boff <- byteOffset df , bsize <- byteSize df+ , steps <- cumulDims $ dims @ns , (# s1, arrM #) <- newAlignedPinnedByteArray# bsize (byteAlign df) s0 , s2 <- copyByteArray# arrA boff arrM 0# bsize s1- = (# s2, MDataFrame# 0# (quotInt# bsize elS) arrM #)+ = (# s2, MDataFrame# 0# steps arrM #) {-# INLINE thawPinDataFrame# #-} -- | UnsafeCoerces an underlying byte array. unsafeThawDataFrame# :: forall (t :: Type) (ns :: [Nat]) s- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . ( Dimensions ns+ , PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> State# s -> (# State# s, MDataFrame s t ns #) unsafeThawDataFrame# df s0 | elS <- byteSize @t undefined- , arrA <- getBytes df+ , arrA <- getBytes df , boff <- byteOffset df- , bsize <- byteSize df+ , steps <- cumulDims $ dims @ns = (# s0- , MDataFrame# (quotInt# boff elS) (quotInt# bsize elS) (unsafeCoerce# arrA)+ , MDataFrame# (quotInt# boff elS) steps (unsafeCoerce# arrA) #) {-# INLINE unsafeThawDataFrame# #-} @@ -181,9 +236,10 @@ -- | Write a single element at the specified index writeDataFrame# :: forall (t :: Type) (ns :: [Nat]) s- . ( PrimBytes t, Dimensions ns )+ . PrimBytes t => MDataFrame s t ns -> Idxs ns -> t -> State# s -> (# State# s, () #)-writeDataFrame# mdf ei | I# i <- fromEnum ei = writeDataFrameOff# mdf i+writeDataFrame# mdf@(MDataFrame# _ st _) ei+ | I# i <- cdIx st ei = writeDataFrameOff# mdf i {-# INLINE writeDataFrame# #-} -- | Read a single element at the specified element offset@@ -195,9 +251,10 @@ -- | Read a single element at the specified index readDataFrame# :: forall (t :: Type) (ns :: [Nat]) s- . ( PrimBytes t, Dimensions ns )+ . PrimBytes t => MDataFrame s t ns -> Idxs ns -> State# s -> (# State# s, t #)-readDataFrame# mdf ei | I# i <- fromEnum ei = readDataFrameOff# mdf i+readDataFrame# mdf@(MDataFrame# _ st _) ei+ | I# i <- cdIx st ei = readDataFrameOff# mdf i {-# INLINE readDataFrame# #-} -- | Allow arbitrary operations on a pointer to the beginning of the data.
+ src/Numeric/DataFrame/Internal/PrimArray.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE UnboxedTuples #-}+module Numeric.DataFrame.Internal.PrimArray+ ( PrimArray (..), CumulDims (..)+ , cumulDims, cdTotalDim, cdTotalDim#, cdIx+ , ixOff, unsafeFromFlatList, getSteps, fromSteps+ ) where++import Data.Monoid as Mon (Monoid (..))+import Data.Semigroup as Sem (Semigroup (..))+import GHC.Base (ByteArray#, Int (..), Int#, Word (..), word2Int#)+import Numeric.Dimensions+import Numeric.PrimBytes++-- | Given @Dims ns@, @CumulativeDims@ is a list of length @Length ns + 1@;+-- which cumulative @totalDim@ accumulated on the right.+-- In particular, its first element is @totalDim ds@,+-- its last element is always is always @1@.+newtype CumulDims = CumulDims { unCumulDims :: [Word] }++instance Sem.Semigroup CumulDims where+ CumulDims as <> CumulDims bs = CumulDims $ map (head bs *) (init as) ++ bs++instance Mon.Monoid CumulDims where+ mempty = CumulDims [1]+#if !(MIN_VERSION_base(4,11,0))+ mappend = (<>)+#endif+++-- | Calculate cumulative dims+cumulDims :: Dims (ns :: [k]) -> CumulDims+cumulDims = CumulDims . uncurry (:)+ . foldr (\d (c, cs) -> (c*d,c:cs)) (1, []) . listDims++-- | Get the total number of elements+cdTotalDim :: CumulDims -> Word+cdTotalDim ~(CumulDims ~(n:_)) = n++cdTotalDim# :: CumulDims -> Int#+cdTotalDim# ~(CumulDims ~(n:_)) = case n of W# w -> word2Int# w++-- | Calculate offset of an Idxs+--+-- Note, you can take offset of subspace with CumulDims of larger space+-- - very convenient!+cdIx :: CumulDims -> Idxs ns -> Int+cdIx ~(CumulDims ~(_:steps))+ = fromIntegral . sum . zipWith (*) steps . listIdxs++-- | Try to get @CumulDims@ from an array,+-- and create it using @Dims@ if failed.+getSteps :: PrimArray t a => Dims (ns :: [k]) -> a -> CumulDims+getSteps dds df = case uniqueOrCumulDims df of+ Left _ -> cumulDims dds+ Right ds -> ds+{-# INLINE getSteps #-}++-- | Get @Dims@ by "de-accumulating" @CumulDims@.+fromSteps :: CumulDims -> SomeDims+fromSteps = someDimsVal . f . unCumulDims+ where+ -- ignore last value, which is always 1+ f :: [Word] -> [Word]+ f [] = []+ f [_] = []+ f [n,_] = [n]+ f (a:b:cs) = a `quot` b : f (b:cs)+{-# INLINE fromSteps #-}++class PrimBytes t => PrimArray t a | a -> t where+ -- | Broadcast element into array+ broadcast :: t -> a+ -- | Index an array given an offset+ ix# :: Int# -> a -> t+ -- | Generate an array using an accumulator funtion+ gen# :: CumulDims+ -- ^ Dimensionality of the result array;+ -- Be careful! @ns@ depends on @a@, but this is not reflected in+ -- types and is not checked at runtime.+ -> (s -> (# s, t #))+ -> s -> (# s, a #)+ -- | update a single element in an array given an offset+ upd# :: CumulDims+ -- ^ Dimensionality of the result array;+ -- Be careful! @ns@ depends on @a@, but this is not reflected in+ -- types and is not checked at runtime.+ -> Int# -> t -> a -> a++ -- | If the array represented as a single broadcasted value,+ -- return this value.+ -- Otherwise, return full array content:+ -- @CumulDims@, array offset (elements), byte array with the content.+ arrayContent# :: a -> (# t | (# CumulDims, Int#, ByteArray# #) #)++ -- | Offset of an array as a number of elements+ offsetElems :: a -> Int#+ offsetElems a = case arrayContent# a of+ (# _ | #) -> 0#+ (# | (# _, o, _ #) #) -> o+ {-# INLINE offsetElems #-}++ -- | Normally, this returns a cumulative @totalDim@s.+ -- However, if a particular implementation does not have the dimensionality+ -- information, it cannot return @CumulDims@;+ -- In this case, it is a sign that all elements of an array are same.+ -- Thus, it is possible to return the single element value instead.+ --+ -- Note, this function returns the only unique element only if it is+ -- a such by construction (there is no equality checks involved).+ uniqueOrCumulDims :: a -> Either t CumulDims+ uniqueOrCumulDims a = case arrayContent# a of+ (# x | #) -> Left x+ (# | (# cd, _, _ #) #) -> Right cd+ {-# INLINE uniqueOrCumulDims #-}++ -- | Get array by its offset and cumulative dims in a ByteArray.+ -- Both offset and dims are given in element number (not in bytes).+ --+ -- It is better to use this function instead of @fromBytes@ to avoid+ -- recalculating @CumulDims@ for implementations that require it.+ fromElems :: CumulDims -> Int# -> ByteArray# -> a++-- | Index array by an integer offset (starting from 0).+ixOff :: PrimArray t a => Int -> a -> t+ixOff (I# i) = ix# i++-- | Construct an array from a flat list and @Dims@;+-- Be careful! @ns@ depends on @a@, but this is not reflected in+-- types and is not checked at runtime.+unsafeFromFlatList :: PrimArray t a => Dims ns -> t -> [t] -> a+unsafeFromFlatList ds x0 vs = case gen# (cumulDims ds) f vs of (# _, r #) -> r+ where+ f [] = (# [], x0 #)+ f (x:xs) = (# xs, x #)
src/Numeric/DataFrame/ST.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-}@@ -17,8 +16,6 @@ -- Copyright : (c) Artem Chirkin -- License : BSD3 ----- Maintainer : chirkin@arch.ethz.ch--- -- Mutable DataFrames living in ST. -- -----------------------------------------------------------------------------@@ -27,6 +24,7 @@ ( STDataFrame (XSTFrame), SomeSTDataFrame (..) , newDataFrame, newPinnedDataFrame , copyDataFrame, copyMutableDataFrame+ , copyDataFrame', copyMutableDataFrame' , freezeDataFrame, unsafeFreezeDataFrame , thawDataFrame, thawPinDataFrame, unsafeThawDataFrame , writeDataFrame, writeDataFrameOff@@ -35,14 +33,13 @@ ) where -import GHC.Base-import GHC.ST (ST (..))+import GHC.Base+import GHC.ST (ST (..)) -import Numeric.DataFrame.Family-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Mutable-import Numeric.Dimensions-import Numeric.PrimBytes+import Numeric.DataFrame.Internal.Mutable+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.Type+import Numeric.Dimensions -- | Mutable DataFrame that lives in ST.@@ -79,31 +76,69 @@ -- | Copy one DataFrame into another mutable DataFrame at specified position.-copyDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat)- (bs :: [Nat]) (asbs :: [Nat]) s- . ( PrimBytes t- , PrimBytes (DataFrame t (as +: b'))+--+-- In contrast to @copyMDataFrame'@, this function allows to copy over a range of contiguous+-- indices over a single dimension.+-- For example, you can write a 3x4 matrix into a 7x4 matrix, starting at indices 0..3.+copyDataFrame :: forall (t :: Type)+ (b :: Nat) (bi :: Nat) (bd :: Nat)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( b ~ (bi + bd - 1)+ , PrimBytes t+ , PrimBytes (DataFrame t (bd :+ bs)) , ConcatList as (b :+ bs) asbs- , Dimensions (b :+ bs) )- => DataFrame t (as +: b') -> Idxs (b :+ bs) -> STDataFrame s t asbs -> ST s ()-copyDataFrame df ei (STDataFrame mdf) = ST (copyDataFrame# df ei mdf)+ => Idxs (as +: bi) -> DataFrame t (bd :+ bs)+ -> STDataFrame s t asbs -> ST s ()+copyDataFrame ei df (STDataFrame mdf) = ST (copyDataFrame# ei df mdf) {-# INLINE copyDataFrame #-} -- | Copy one mutable DataFrame into another mutable DataFrame at specified position.-copyMutableDataFrame :: forall (t :: Type) (as :: [Nat]) (b' :: Nat) (b :: Nat)- (bs :: [Nat]) (asbs :: [Nat]) s- . ( PrimBytes t+--+-- In contrast to @copyMDataFrame'@, this function allows to copy over a range of contiguous+-- indices over a single dimension.+-- For example, you can write a 3x4 matrix into a 7x4 matrix, starting at indices 0..3.+copyMutableDataFrame :: forall (t :: Type)+ (b :: Nat) (bi :: Nat) (bd :: Nat)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( b ~ (bi + bd - 1)+ , PrimBytes t , ConcatList as (b :+ bs) asbs- , Dimensions (b :+ bs) )- => STDataFrame s t (as +: b') -> Idxs (b :+ bs)+ => Idxs (as +: bi) -> STDataFrame s t (bd :+ bs) -> STDataFrame s t asbs -> ST s ()-copyMutableDataFrame (STDataFrame mdfA) ei (STDataFrame mdfB)- = ST (copyMDataFrame# mdfA ei mdfB)+copyMutableDataFrame ei (STDataFrame mdfA) (STDataFrame mdfB)+ = ST (copyMDataFrame# ei mdfA mdfB) {-# INLINE copyMutableDataFrame #-} +-- | Copy one DataFrame into another mutable DataFrame at specified position.+--+-- This is a simpler version of @copyDataFrame@ that allows to copy over one index at a time.+copyDataFrame' :: forall (t :: Type)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( PrimBytes t+ , PrimBytes (DataFrame t bs)+ , ConcatList as bs asbs+ )+ => Idxs as -> DataFrame t bs+ -> STDataFrame s t asbs -> ST s ()+copyDataFrame' ei df (STDataFrame mdf) = ST (copyDataFrame'# ei df mdf)+{-# INLINE copyDataFrame' #-} +-- | Copy one mutable DataFrame into another mutable DataFrame at specified position.+--+-- This is a simpler version of @copyDataFrame@ that allows to copy over one index at a time.+copyMutableDataFrame' :: forall (t :: Type)+ (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) s+ . ( PrimBytes t+ , ConcatList as bs asbs+ )+ => Idxs as -> STDataFrame s t bs+ -> STDataFrame s t asbs -> ST s ()+copyMutableDataFrame' ei (STDataFrame mdfA) (STDataFrame mdfB)+ = ST (copyMDataFrame'# ei mdfA mdfB)+{-# INLINE copyMutableDataFrame' #-}+ -- | Make a mutable DataFrame immutable, without copying. unsafeFreezeDataFrame :: forall (t :: Type) (ns :: [Nat]) s . PrimArray t (DataFrame t ns)@@ -121,7 +156,7 @@ -- | Create a new mutable DataFrame and copy content of immutable one in there. thawDataFrame :: forall (t :: Type) (ns :: [Nat]) s- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> ST s (STDataFrame s t ns) thawDataFrame df = STDataFrame <$> ST (thawDataFrame# df) {-# INLINE thawDataFrame #-}@@ -129,14 +164,15 @@ -- | Create a new mutable DataFrame and copy content of immutable one in there. -- The result array is pinned and aligned. thawPinDataFrame :: forall (t :: Type) (ns :: [Nat]) s- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . (Dimensions ns, PrimBytes (DataFrame t ns)) => DataFrame t ns -> ST s (STDataFrame s t ns) thawPinDataFrame df = STDataFrame <$> ST (thawPinDataFrame# df) {-# INLINE thawPinDataFrame #-} -- | UnsafeCoerces an underlying byte array. unsafeThawDataFrame :: forall (t :: Type) (ns :: [Nat]) s- . (PrimBytes (DataFrame t ns), PrimBytes t)+ . ( Dimensions ns+ , PrimBytes (DataFrame t ns), PrimBytes t) => DataFrame t ns -> ST s (STDataFrame s t ns) unsafeThawDataFrame df = STDataFrame <$> ST (unsafeThawDataFrame# df) {-# INLINE unsafeThawDataFrame #-}@@ -144,7 +180,7 @@ -- | Write a single element at the specified index writeDataFrame :: forall t (ns :: [Nat]) s- . ( PrimBytes t, Dimensions ns )+ . PrimBytes t => STDataFrame s t ns -> Idxs ns -> DataFrame t ('[] :: [Nat]) -> ST s () writeDataFrame (STDataFrame mdf) ei = ST . writeDataFrame# mdf ei . unsafeCoerce# {-# INLINE writeDataFrame #-}@@ -152,7 +188,7 @@ -- | Read a single element at the specified index readDataFrame :: forall (t :: Type) (ns :: [Nat]) s- . ( PrimBytes t, Dimensions ns )+ . PrimBytes t => STDataFrame s t ns -> Idxs ns -> ST s (DataFrame t ('[] :: [Nat])) readDataFrame (STDataFrame mdf) = unsafeCoerce# . ST . readDataFrame# mdf {-# INLINE readDataFrame #-}@@ -178,7 +214,7 @@ -- | Check if the byte array wrapped by this DataFrame is pinned, -- which means cannot be relocated by GC.-isDataFramePinned :: forall (t :: Type) (ns :: [k]) s+isDataFramePinned :: forall (k :: Type) (t :: Type) (ns :: [k]) s . KnownDimKind k => STDataFrame s t ns -> Bool isDataFramePinned df = case dimKind @k of
− src/Numeric/DataFrame/Shape.hs
@@ -1,238 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UnboxedTuples #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}--------------------------------------------------------------------------------- |--- Module : Numeric.DataFrame.Shape--- Copyright : (c) Artem Chirkin--- License : BSD3------ Maintainer : chirkin@arch.ethz.ch------ Construct new DataFrames from pieces.-----------------------------------------------------------------------------------module Numeric.DataFrame.Shape- ( (<:>), (<::>), (<+:>)- , fromScalar- , DataFrameToList (..)- , fromListN, fromList- ) where--import GHC.Base--import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.Family (inferASing, inferPrim,- inferPrimElem)-import Numeric.DataFrame.SubSpace-import Numeric.DataFrame.Type (DataFrame (..))-import Numeric.Dimensions-import Numeric.PrimBytes-import Numeric.Scalar as Scalar-import Numeric.TypedList (TypedList (..))-import qualified Numeric.TypedList as Dims-import Numeric.Vector----- | Append one DataFrame to another, sum up last dimension-(<:>) :: forall (n :: Nat) (m :: Nat) (npm :: Nat) (ds :: [Nat])- (t :: Type)- . ( PrimBytes (DataFrame t (ds +: n))- , PrimBytes (DataFrame t (ds +: m))- , PrimBytes (DataFrame t (ds +: npm))- , npm ~ (n + m)- , n ~ (npm - m)- , m ~ (npm - n)- )- => DataFrame t (ds +: n)- -> DataFrame t (ds +: m)- -> DataFrame t (ds +: npm)-(<:>) = appendDF-infixl 5 <:>-{-# INLINE [1] (<:>) #-}---- | Append one DataFrame to another,--- add another @Dim = 2@ to their dimension list.-(<::>) :: forall (ds :: [Nat]) (t :: Type)- . ( PrimBytes (DataFrame t ds)- , PrimBytes (DataFrame t ds)- , PrimBytes (DataFrame t (ds +: 2 :: [Nat]))- )- => DataFrame t ds- -> DataFrame t ds- -> DataFrame t (ds +: 2 :: [Nat])-(<::>) = appendDF-infixl 5 <::>-{-# INLINE [1] (<::>) #-}---vec2t :: forall t . SubSpace t '[] '[2] '[2] => Scalar t -> Scalar t -> Vector t 2-vec2t = unsafeCoerce# (vec2 @t)-{-# INLINE vec2t #-}--{-# RULES-"<::>/vec2-Float" (<::>) = vec2t @Float-"<::>/vec2-Double" (<::>) = vec2t @Double-"<::>/vec2-Int" (<::>) = vec2t @Int-"<::>/vec2-Word" (<::>) = vec2t @Word- #-}---- | Grow the first DataFrame by adding the second one to it--- incrementing the last Dim in the list.-(<+:>) :: forall (ds :: [Nat]) (n :: Nat) (m :: Nat) (t :: Type)- . ( PrimBytes (DataFrame t (ds +: n))- , PrimBytes (DataFrame t ds)- , PrimBytes (DataFrame t (ds +: m))- , m ~ (n + 1)- )- => DataFrame t (ds +: n)- -> DataFrame t ds- -> DataFrame t (ds +: m)-(<+:>) = appendDF-infixl 5 <+:>-{-# INLINE [1] (<+:>) #-}----- | Concatenate a list of @DataFrame@s.--- Returns @Nothing@ if the list does not have enough elements.------ Input must be parametrized by @[Nat]@ to make sure every element--- in the input list has the same dimensionality.--- Output is in @[XNat]@, because the last dimension is unknown at compile time.-fromList :: forall m ns t- . ( Dimensions ns- , PrimBytes t- )- => Dim m- -- ^ Minimum number of elements in a list- -> [DataFrame t ns]- -- ^ List of frames to concatenate- -> Maybe (DataFrame t (AsXDims ns +: XN m))-fromList d xs = fromListN d (length xs) xs------ | Implement function `toList`.--- We need to create a dedicated type class for this--- to make it polymorphic over kind k (Nat <-> XNat).-class DataFrameToList (t :: Type) (ds :: [k]) (z :: k) where- -- | Unwrap the last dimension of a DataFrame into a list of smaller frames- toList :: DataFrame t (ds +: z) -> [DataFrame t ds]----instance ( Dimensions (ns +: z)- , PrimBytes t- )- => DataFrameToList t (ns :: [Nat]) (z :: Nat) where- toList df- | Dims.Snoc (Dims :: Dims ns') dn <- dims @Nat @(ns +: z)- -- TODO: line below is a workaround and should be avoided.- , E <- unsafeCoerce# (E @(ns ~ ns)) :: Evidence (ns ~ ns')- , E <- inferASing @t @ns- , E <- inferASing @t @(ns +: z)- , E <- inferPrim @t @(ns +: z)- , E <- inferPrim @t @ns- , n <- dimVal dn- , I# step <- fromIntegral $ totalDim' @ns- , off0 <- elemOffset df- , ba <- getBytes df- = let go 0 _ = []- go k off = fromElems off step ba : go (k-1) (off +# step)- in go n off0- | otherwise = []--instance DataFrameToList t (xns :: [XNat]) (xz :: XNat) where- toList (XFrame (df :: DataFrame t nsz))- | nsz <- dims @Nat @nsz- , xnsz <- xDims @(xns +: xz) nsz- -- TODO: line below is a workaround and should be avoided.- , E <- unsafeCoerce# (E @(xns ~ xns)) :: Evidence (xns ~ Init (xns +: xz))- , xns <- Dims.init xnsz- , TypeList <- types xnsz- , EvList <- Dims.init (EvList @_ @KnownXNatType @(xns +: xz))- , Dims.Snoc (ns@Dims :: Dims ns) _ <- nsz- , Dims.Cons (_ :: Dim k) (_ :: Dims ks) <- nsz- , E <- inferPrimElem @t @k @ks- , XDims ns' <- xns- , Just E <- sameDims ns ns'- , E <- inferASing @t @ns- = map XFrame (toList df)- toList _ = []---- | Concatenate a list of @DataFrame@s.--- Returns @Nothing@ if the list does not have enough elements--- or if provided length is invalid.-fromListN :: forall (m :: Nat) (ns :: [Nat]) (t :: Type)- . ( Dimensions ns- , PrimBytes t- )- => Dim m- -- ^ Minimum number of elements in a list- -> Int- -- ^ How many elements of a list to take.- -- Must be not smaller than @m@ and not greater than @length ns@.- -> [DataFrame t ns]- -- ^ List of frames to concatenate- -> Maybe (DataFrame t (AsXDims ns +: XN m))-fromListN Dim n@(I# n#) xs'- | n < 0 = Nothing- | Just dxn@(Dx dn@(D :: Dim n)) <- constrain @m (someDimVal (fromIntegral n))- , Just xs <- takeMaybe n xs'- , ns@(AsXDims xns) <- dims @Nat @ns- , nsn@Dims <- Dims.snoc ns dn- , xnsn <- Dims.snoc xns dxn- , EvList <- Dims.snoc (EvList @XNat @KnownXNatType @(AsXDims ns))- (toEvidence' (E @(KnownXNatType (XN m))))- , XDims nsn' <- xnsn- , Just E <- sameDims nsn nsn'- , E <- inferASing @t @ns- , E <- inferASing @t @(ns +: n)- , E <- inferPrim @t @ns- , E <- inferPrim @t @(ns +: n)- , I# partElN <- fromIntegral $ totalDim' @ns- , totalElN <- partElN *# n#- , elS <- byteSize @t undefined- , partBS <- partElN *# elS- = case runRW#- ( \s0 -> case newByteArray# (totalElN *# elS) s0 of- (# s1, mba #) ->- let go _ [] s = s- go off (p : ps) s = go (off +# partBS) ps (writeBytes mba off p s)- in unsafeFreezeByteArray# mba (go 0# xs s1)- ) of (# _, r #)- -> Just (XFrame (fromElems 0# totalElN r :: DataFrame t (ns +: n)))-fromListN _ _ _ = Nothing--takeMaybe :: Int -> [a] -> Maybe [a]-takeMaybe 0 _ = Just []-takeMaybe _ [] = Nothing-takeMaybe n (x : xs) = (x:) <$> takeMaybe (n-1) xs----appendDF :: (PrimBytes x, PrimBytes y, PrimBytes z)- => x -> y -> z-appendDF x y- | sx <- byteSize x- = case runRW#- ( \s0 -> case newByteArray# (sx +# byteSize y) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( writeBytes mba sx y- ( writeBytes mba 0# x s1))- ) of (# _, r #) -> fromBytes 0# r-{-# INLINE appendDF #-}
src/Numeric/DataFrame/SubSpace.hs view
@@ -3,8 +3,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -20,31 +18,30 @@ -- Copyright : (c) Artem Chirkin -- License : BSD3 ----- Maintainer : chirkin@arch.ethz.ch ----- ----------------------------------------------------------------------------- module Numeric.DataFrame.SubSpace- ( SubSpace (..), (!), (!.), element+ ( SubSpace (..), (!), element , ewfoldMap, iwfoldMap , ewzip, iwzip , indexWise_, elementWise_ ) where -import GHC.Base+import Data.Kind+import GHC.Exts -import Numeric.DataFrame.Family-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.PrimOps-import Numeric.Dimensions-import Numeric.PrimBytes+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.Type+import Numeric.Dimensions+import Numeric.PrimBytes + -- | Operations on DataFrames ----- @as@ is an element dimensionality+-- @as@ is an indexing dimensionality ----- @bs@ is an indexing dimensionality+-- @bs@ is an element dimensionality -- -- @t@ is an underlying data type (i.e. Float, Int, Double) --@@ -52,92 +49,366 @@ , Dimensions as , Dimensions bs , Dimensions asbs+ , PrimArray t (DataFrame t bs) , PrimArray t (DataFrame t asbs)+ , PrimBytes (DataFrame t bs)+ , PrimBytes (DataFrame t asbs) ) => SubSpace (t :: Type) (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) | asbs as -> bs, asbs bs -> as, as bs -> asbs where+ -- | Unsafely get a sub-dataframe by its primitive element offset. -- The offset is not checked to be aligned to the space structure or for bounds.- -- Arguments are zero-based primitive element offset and subset ("as" element) size (aka `totalDim` of sub dataframe)+ -- Arguments are zero-based primitive element offset and subset ("bs" element)+ -- size (aka `totalDim` of sub dataframe) -- -- Normal indexing can be expressed in terms of `indexOffset#`: --- -- > i !. x = case (# dimVal (dim @as), fromEnum i #) of (# I# n, I# j #) -> indexOffset# (n *# j) n x+ -- > index i = case (# dimVal (dim @bs), fromEnum i #) of (# I# n, I# j #) -> indexOffset# (n *# j) indexOffset# :: Int# -- ^ Prim element offset- -> Int# -- ^ Number of prim elements in the prefix subspace- -> DataFrame t asbs -> DataFrame t as+ -> DataFrame t asbs -> DataFrame t bs+ indexOffset# off df = case uniqueOrCumulDims df of+ Left a -> broadcast a+ Right steps -> fromElems (dropPref (dims @as) steps) (offsetElems df +# off) (getBytes df)+ {-# INLINE [1] indexOffset# #-}++ -- | Unsafely update a sub-dataframe by its primitive element offset.+ -- The offset is not checked to be aligned to the space structure or for bounds.+ -- Arguments are zero-based primitive element offset and subset ("bs" element)+ -- size (aka `totalDim` of sub dataframe)+ --+ -- Normal updating can be expressed in terms of `indexOffset#`:+ --+ -- > update i = case (# dimVal (dim @bs), fromEnum i #) of (# I# n, I# j #) -> updateOffset# (n *# j)+ updateOffset# :: Int# -- ^ Prim element offset+ -> DataFrame t bs -> DataFrame t asbs -> DataFrame t asbs+ updateOffset# off x df+ | steps <- getSteps (dims @asbs) df+ , elemBS <- byteSize @t undefined = case runRW#+ ( \s0 -> case newByteArray# (cdTotalDim# steps *# elemBS) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( writeBytes mba (off *# elemBS) x+ ( writeBytes mba 0# df s1 )+ )+ ) of (# _, r #) -> fromElems steps 0# r+ {-# INLINE [1] updateOffset# #-}++ -- | Get an element by its index in the dataframe+ index :: Idxs as -> DataFrame t asbs -> DataFrame t bs+ index i df = case uniqueOrCumulDims df of+ Left a -> broadcast a+ Right steps -> case cdIx steps i of+ I# off -> fromElems (dropPref (dims @as) steps) (offsetElems df +# off) (getBytes df)+ {-# INLINE [1] index #-}++ -- | Get a few contiguous elements.+ --+ -- In a sense, this is just a more complicated version of `index`.+ slice :: forall (bi :: Nat) (bd :: Nat) (b' :: Nat) (bs' :: [Nat])+ . ( b' ~ (bi + bd - 1), bs ~ (b' :+ bs'), KnownDim bd)+ => Idxs (as +: bi) -> DataFrame t asbs -> DataFrame t (bd :+ bs')+ slice i df+ | _ :* Dims <- dims @bs+ , Dict <- inferKnownBackend @t @(bd ': bs')+ = case uniqueOrCumulDims df of+ Left a -> broadcast a+ Right steps -> case cdIx steps i of+ I# off+ | bsteps <- repHead (dimVal' @bd) (dropPref (dims @as) steps)+ -> fromElems bsteps (offsetElems df +# off) (getBytes df)+ | otherwise = error "SubSpace/slice: impossible arguments"+ where+ repHead y (CumulDims (_:x:xs)) = CumulDims (y*x:x:xs)+ repHead _ steps = steps+ -- | Set a new value to an element- update :: Idxs bs -> DataFrame t as -> DataFrame t asbs -> DataFrame t asbs+ update :: Idxs as -> DataFrame t bs -> DataFrame t asbs -> DataFrame t asbs+ update i x df+ | steps <- getSteps (dims @asbs) df+ , I# off <- cdIx steps i+ , elemBS <- byteSize @t undefined = case runRW#+ ( \s0 -> case newByteArray# (cdTotalDim# steps *# elemBS) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( writeBytes mba (off *# elemBS) x+ ( writeBytes mba 0# df s1 )+ )+ ) of (# _, r #) -> fromElems steps 0# r+ {-# INLINE [1] update #-}++ -- | Update a few contiguous elements+ --+ -- In a sense, this is just a more complicated version of `update`.+ updateSlice :: forall (bi :: Nat) (bd :: Nat) (b' :: Nat) (bs' :: [Nat])+ . ( b' ~ (bi + bd - 1), bs ~ (b' :+ bs'), KnownDim bd)+ => Idxs (as +: bi) -> DataFrame t (bd :+ bs') -> DataFrame t asbs -> DataFrame t asbs+ updateSlice i x df+ | _ :* Dims <- dims @bs+ , Dict <- inferKnownBackend @t @(bd ': bs')+ , steps <- getSteps (dims @asbs) df+ , I# off <- cdIx steps i+ , elemBS <- byteSize @t undefined = case runRW#+ ( \s0 -> case newByteArray# (cdTotalDim# steps *# elemBS) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( writeBytes mba (off *# elemBS) x+ ( writeBytes mba 0# df s1 )+ )+ ) of (# _, r #) -> fromElems steps 0# r+ | otherwise = error "SubSpace/updateSlice: impossible arguments"+ {-# INLINE [1] updateSlice #-}+ -- | Map a function over each element of DataFrame- ewmap :: forall s (as' :: [Nat]) (asbs' :: [Nat])- . SubSpace s as' bs asbs'- => (DataFrame s as' -> DataFrame t as)+ ewmap :: forall s (bs' :: [Nat]) (asbs' :: [Nat])+ . SubSpace s as bs' asbs'+ => (DataFrame s bs' -> DataFrame t bs) -> DataFrame s asbs' -> DataFrame t asbs+ ewmap f df+ | bsizeT <- byteSize @t undefined+ , stepsAS <- cumulDims $ dims @as+ , stepsBS <- cumulDims $ dims @bs+ , stepsBS' <- cumulDims $ dims @bs'+ , stepsASBS <- stepsAS <> stepsBS+ , lenAS <- cdTotalDim# stepsAS+ , lenBS <- cdTotalDim# stepsBS+ , lenBS' <- cdTotalDim# stepsBS'+ , lenBSB <- lenBS *# bsizeT+ , lenASBSB <- lenAS *# lenBSB+ = let go mba sourceOffE destOffB s+ | isTrue# (destOffB >=# lenASBSB)+ = s+ | otherwise+ = go mba (sourceOffE +# lenBS') (destOffB +# lenBSB)+ (writeBytes mba destOffB (f (indexOffset# sourceOffE df)) s)+ in case runRW#+ ( \s0 -> case newByteArray# lenASBSB s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba ( go mba 0# 0# s1 )+ ) of (# _, r #) -> fromElems stepsASBS 0# r+ {-# INLINE [1] ewmap #-}+ -- | Map a function over each element with its index of DataFrame- iwmap :: forall s (as' :: [Nat]) (asbs' :: [Nat])- . SubSpace s as' bs asbs'- => (Idxs bs -> DataFrame s as' -> DataFrame t as)+ iwmap :: forall s (bs' :: [Nat]) (asbs' :: [Nat])+ . SubSpace s as bs' asbs'+ => (Idxs as -> DataFrame s bs' -> DataFrame t bs) -> DataFrame s asbs' -> DataFrame t asbs+ iwmap f df+ | bsizeT <- byteSize @t undefined+ , stepsAS <- cumulDims $ dims @as+ , stepsBS <- cumulDims $ dims @bs+ , stepsBS' <- cumulDims $ dims @bs'+ , stepsASBS <- stepsAS <> stepsBS+ , lenAS <- cdTotalDim# stepsAS+ , lenBS <- cdTotalDim# stepsBS+ , lenBS' <- cdTotalDim# stepsBS'+ , lenBSB <- lenBS *# bsizeT+ , lenASBSB <- lenAS *# lenBSB+ = let go _ [] _ _ s = s+ go mba (i:is) sourceOffE destOffB s+ = go mba is (sourceOffE +# lenBS') (destOffB +# lenBSB)+ (writeBytes mba destOffB (f i (indexOffset# sourceOffE df)) s)+ in case runRW#+ ( \s0 -> case newByteArray# lenASBSB s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba ( go mba [minBound..maxBound] 0# 0# s1 )+ ) of (# _, r #) -> fromElems stepsASBS 0# r+ {-# INLINE [1] iwmap #-}+ -- | Generate a DataFrame by repeating an element- ewgen :: DataFrame t as -> DataFrame t asbs+ ewgen :: DataFrame t bs -> DataFrame t asbs+ ewgen df = case uniqueOrCumulDims df of+ Left a -> broadcast a+ Right stepsBS+ | stepsAS <- cumulDims $ dims @as+ , stepsASBS <- stepsAS <> stepsBS+ , elS <- byteSize @t undefined+ , lenBSB <- cdTotalDim# stepsBS *# elS+ , lenASBSB <- cdTotalDim# stepsASBS *# elS+ -> let go mba destOffB s+ | isTrue# (destOffB >=# lenASBSB)+ = s+ | otherwise+ = go mba (destOffB +# lenBSB)+ (writeBytes mba destOffB df s)+ in case runRW#+ ( \s0 -> case newByteArray# lenASBSB s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba ( go mba 0# s1 )+ ) of (# _, r #) -> fromElems stepsASBS 0# r+ {-# INLINE [1] ewgen #-}+ -- | Generate a DataFrame by iterating a function (index -> element)- iwgen :: (Idxs bs -> DataFrame t as) -> DataFrame t asbs+ iwgen :: (Idxs as -> DataFrame t bs) -> DataFrame t asbs+ iwgen f+ | stepsAS <- cumulDims $ dims @as+ , stepsBS <- cumulDims $ dims @bs+ , stepsASBS <- stepsAS <> stepsBS+ , elS <- byteSize @t undefined+ , lenBSB <- cdTotalDim# stepsBS *# elS+ , lenASBSB <- cdTotalDim# stepsASBS *# elS+ = let go _ [] _ s = s+ go mba (i:is) destOffB s+ = go mba is (destOffB +# lenBSB) (writeBytes mba destOffB (f i) s)+ in case runRW#+ ( \s0 -> case newByteArray# lenASBSB s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba ( go mba [minBound..maxBound] 0# s1 )+ ) of (# _, r #) -> fromElems stepsASBS 0# r+ {-# INLINE [1] iwgen #-}+ -- | Left-associative fold of a DataFrame. -- The fold is strict, so accumulater is evaluated to WHNF; -- but you'd better make sure that the function is strict enough to not -- produce memory leaks deeply inside the result data type.- ewfoldl :: (b -> DataFrame t as -> b) -> b -> DataFrame t asbs -> b+ ewfoldl :: (b -> DataFrame t bs -> b) -> b -> DataFrame t asbs -> b+ ewfoldl f x0 df = case uniqueOrCumulDims df of+ Left a ->+ let b = broadcast a+ go 0 x = x+ go n x = go (n-1) $! f x b+ in go (totalDim' @as) x0+ Right stepsASBS+ | stepsBS <- dropPref (dims @as) stepsASBS+ , lenBS <- cdTotalDim# stepsBS+ , lenASBS <- cdTotalDim# stepsASBS+ -> let go sourceOffE x+ | isTrue# (sourceOffE >=# lenASBS)+ = x+ | otherwise+ = go (sourceOffE +# lenBS) $! f x (indexOffset# sourceOffE df)+ in go 0# x0+ -- | Left-associative fold of a DataFrame with an index -- The fold is strict, so accumulater is evaluated to WHNF; -- but you'd better make sure that the function is strict enough to not -- produce memory leaks deeply inside the result data type.- iwfoldl :: (Idxs bs -> b -> DataFrame t as -> b) -> b -> DataFrame t asbs -> b+ iwfoldl :: (Idxs as -> b -> DataFrame t bs -> b) -> b -> DataFrame t asbs -> b+ iwfoldl f x0 df = case uniqueOrCumulDims df of+ Left a ->+ let b = broadcast a+ go [] x = x+ go (i:is) x = go is $! f i x b+ in go [minBound..maxBound] x0+ Right stepsASBS+ | stepsBS <- dropPref (dims @as) stepsASBS+ , lenBS <- cdTotalDim# stepsBS+ -> let go [] _ x = x+ go (i:is) sourceOffE x+ = go is (sourceOffE +# lenBS) $! f i x (indexOffset# sourceOffE df)+ in go [minBound..maxBound] 0# x0+ -- | Right-associative fold of a DataFrame -- The fold is strict, so accumulater is evaluated to WHNF; -- but you'd better make sure that the function is strict enough to not -- produce memory leaks deeply inside the result data type.- ewfoldr :: (DataFrame t as -> b -> b) -> b -> DataFrame t asbs -> b+ ewfoldr :: (DataFrame t bs -> b -> b) -> b -> DataFrame t asbs -> b+ ewfoldr f x0 df = case uniqueOrCumulDims df of+ Left a ->+ let b = broadcast a+ go 0 x = x+ go n x = go (n-1) $! f b x+ in go (totalDim' @as) x0+ Right stepsASBS+ | stepsBS <- dropPref (dims @as) stepsASBS+ , lenBS <- cdTotalDim# stepsBS+ , lenASBS <- cdTotalDim# stepsASBS+ -> let go sourceOffE x+ | isTrue# (sourceOffE <# 0#)+ = x+ | otherwise+ = go (sourceOffE -# lenBS) $! f (indexOffset# sourceOffE df) x+ in go (lenASBS -# lenBS) x0+ -- | Right-associative fold of a DataFrame with an index -- The fold is strict, so accumulater is evaluated to WHNF; -- but you'd better make sure that the function is strict enough to not -- produce memory leaks deeply inside the result data type.- iwfoldr :: (Idxs bs -> DataFrame t as -> b -> b) -> b -> DataFrame t asbs -> b+ iwfoldr :: (Idxs as -> DataFrame t bs -> b -> b) -> b -> DataFrame t asbs -> b+ iwfoldr f x0 df = case uniqueOrCumulDims df of+ Left a ->+ let b = broadcast a+ go [] x = x+ go (i:is) x = go is $! f i b x+ in go [maxBound, pred maxBound .. minBound] x0+ Right stepsASBS+ | stepsBS <- dropPref (dims @as) stepsASBS+ , lenBS <- cdTotalDim# stepsBS+ , lenASBS <- cdTotalDim# stepsASBS+ -> let go [] _ x = x+ go (i:is) sourceOffE x+ = go is (sourceOffE -# lenBS) $! f i (indexOffset# sourceOffE df) x+ in go [maxBound, pred maxBound .. minBound] (lenASBS -# lenBS) x0+ -- | Apply an applicative functor on each element (Lens-like traversal)- elementWise :: forall s (as' :: [Nat]) (asbs' :: [Nat]) f+ elementWise :: forall (s :: Type) (bs' :: [Nat]) (asbs' :: [Nat]) (f :: Type -> Type) . ( Applicative f- , SubSpace s as' bs asbs'+ , SubSpace s as bs' asbs' )- => (DataFrame s as' -> f (DataFrame t as))+ => (DataFrame s bs' -> f (DataFrame t bs)) -> DataFrame s asbs' -> f (DataFrame t asbs)+ elementWise = indexWise . const+ {-# INLINE [1] elementWise #-}+ -- | Apply an applicative functor on each element with its index -- (Lens-like indexed traversal)- indexWise :: forall s (as' :: [Nat]) (asbs' :: [Nat]) f+ indexWise :: forall (s :: Type) (bs' :: [Nat]) (asbs' :: [Nat]) (f :: Type -> Type) . ( Applicative f- , SubSpace s as' bs asbs'+ , SubSpace s as bs' asbs' )- => (Idxs bs -> DataFrame s as' -> f (DataFrame t as))+ => (Idxs as -> DataFrame s bs' -> f (DataFrame t bs)) -> DataFrame s asbs' -> f (DataFrame t asbs)+ indexWise f df = runWithState <$> iwfoldl applyF (pure initialState) df+ where+ steps = cumulDims $ dims @asbs+ -- run a state-based continuation within RW+ runWithState :: ( State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))+ -> DataFrame t asbs+ runWithState g = case runRW#+ ( \s0 -> case g s0 of+ (# s1, (# marr, _ #) #) -> unsafeFreezeByteArray# marr s1+ ) of (# _, arr #) -> fromElems steps 0# arr --- | Get an element by its index in the dataframe-(!.) :: forall t as bs asbs- . SubSpace t as bs asbs- => Idxs bs -> DataFrame t asbs -> DataFrame t as-(!.) i = case (# totalDim (dims @_ @as), fromEnum i #) of- (# W# n, I# j #) -> indexOffset# (word2Int# n *# j) (word2Int# n)-{-# INLINE [1] (!.) #-}-infixr 4 !.+ -- Prepare empty byte array for the result DataFrame and keep a current position counter+ -- Input: state+ -- Output: state ++ -- ( current mutable byte array + current write position )+ initialState :: State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #)+ initialState s0 = case newByteArray# (rezLength# *# rezElBSize#) s0 of+ (# s1, marr #) -> (# s1, (# marr, 0# #) #) + -- Given the result chunk, write it into a mutable array+ updateChunk :: (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))+ -> DataFrame t bs+ -> (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))+ updateChunk g dfChunk = case (# byteOffset dfChunk, getBytes dfChunk #) of+ (# off#, arr# #) -> \s -> case g s of+ (# s1, (# marr#, pos# #) #) -> case+ copyByteArray# arr# (off# *# rezElBSize#)+ marr# (pos# *# rezElBSize#)+ (rezStepN# *# rezElBSize#) s1 of+ s2 -> (# s2, (# marr#, pos# +# rezStepN# #) #)++ -- Apply applicative functor on each chunk and update a state.+ applyF :: Idxs as+ -> f (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))+ -> DataFrame s bs'+ -> f (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))+ applyF idx s dfChunk = idx `seq` dfChunk `seq` updateChunk <$> s <*> f idx dfChunk++ -- Element byte size of the result DataFrame (byte size of s)+ rezElBSize# = byteSize @t undefined+ -- Number of primitive elements in the result DataFrame chunk+ !(I# rezStepN#) = fromIntegral $ totalDim' @bs+ -- Number of primitive elements in the result DataFrame+ rezLength# = cdTotalDim# steps+++ -- | Apply an applicative functor on each element with its index -- (Lens-like indexed traversal) indexWise_ :: forall t as bs asbs f b . (SubSpace t as bs asbs, Applicative f)- => (Idxs bs -> DataFrame t as -> f b)+ => (Idxs as -> DataFrame t bs -> f b) -> DataFrame t asbs -> f () indexWise_ f = iwfoldr (\i -> (*>) . f i) (pure ()) -- | Apply an applicative functor on each element (Lens-like traversal) elementWise_ :: forall t as bs asbs f b . (SubSpace t as bs asbs, Applicative f)- => (DataFrame t as -> f b)+ => (DataFrame t bs -> f b) -> DataFrame t asbs -> f () elementWise_ f = ewfoldr ((*>) . f) (pure ()) @@ -145,29 +416,30 @@ -- | Apply a functor over a single element (simple lens) element :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) f . (SubSpace t as bs asbs, Applicative f)- => Idxs bs- -> (DataFrame t as -> f (DataFrame t as))+ => Idxs as+ -> (DataFrame t bs -> f (DataFrame t bs)) -> DataFrame t asbs -> f (DataFrame t asbs)-element i f df = flip (update i) df <$> f (i !. df)+element i f df = flip (update i) df <$> f (index i df) {-# INLINE element #-} --- | Index an element (reverse of !.)+-- | Index an element (reverse arguments of `index`) (!) :: SubSpace t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])- => DataFrame t asbs -> Idxs bs -> DataFrame t as-(!) = flip (!.)-infixl 4 !+ => DataFrame t asbs -> Idxs as -> DataFrame t bs+(!) = flip index {-# INLINE (!) #-}+infixl 4 ! + ewfoldMap :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) m . (Monoid m, SubSpace t as bs asbs)- => (DataFrame t as -> m) -> DataFrame t asbs -> m+ => (DataFrame t bs -> m) -> DataFrame t asbs -> m ewfoldMap f = ewfoldl (\m b -> m `seq` (mappend m $! f b)) mempty {-# INLINE ewfoldMap #-} iwfoldMap :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) m . ( Monoid m, SubSpace t as bs asbs)- => (Idxs bs -> DataFrame t as -> m) -> DataFrame t asbs -> m+ => (Idxs as -> DataFrame t bs -> m) -> DataFrame t asbs -> m iwfoldMap f = iwfoldl (\i m b -> m `seq` (mappend m $! f i b)) mempty {-# INLINE iwfoldMap #-} @@ -175,30 +447,30 @@ -- | Zip two spaces on a specified subspace index-wise (with index) iwzip :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])- s (as' :: [Nat]) (asbs' :: [Nat])- r (as'' :: [Nat]) (asbs'' :: [Nat])+ s (bs' :: [Nat]) (asbs' :: [Nat])+ r (bs'' :: [Nat]) (asbs'' :: [Nat]) . ( SubSpace t as bs asbs- , SubSpace s as' bs asbs'- , SubSpace r as'' bs asbs''+ , SubSpace s as bs' asbs'+ , SubSpace r as bs'' asbs'' )- => (Idxs bs -> DataFrame t as -> DataFrame s as' -> DataFrame r as'')+ => (Idxs as -> DataFrame t bs -> DataFrame s bs' -> DataFrame r bs'') -> DataFrame t asbs -> DataFrame s asbs' -> DataFrame r asbs'' iwzip f dft dfs = iwmap g dft where- g i dft' = f i dft' (i !. dfs)+ g i dft' = f i dft' (index i dfs) {-# INLINE iwzip #-} -- | Zip two spaces on a specified subspace element-wise (without index) ewzip :: forall t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat])- s (as' :: [Nat]) (asbs' :: [Nat])- r (as'' :: [Nat]) (asbs'' :: [Nat])+ s (bs' :: [Nat]) (asbs' :: [Nat])+ r (bs'' :: [Nat]) (asbs'' :: [Nat]) . ( SubSpace t as bs asbs- , SubSpace s as' bs asbs'- , SubSpace r as'' bs asbs''+ , SubSpace s as bs' asbs'+ , SubSpace r as bs'' asbs'' )- => (DataFrame t as -> DataFrame s as' -> DataFrame r as'')+ => (DataFrame t bs -> DataFrame s bs' -> DataFrame r bs'') -> DataFrame t asbs -> DataFrame s asbs' -> DataFrame r asbs''@@ -210,194 +482,16 @@ , Dimensions as , Dimensions bs , Dimensions asbs- , PrimArray t (DataFrame t as)+ , PrimArray t (DataFrame t bs) , PrimArray t (DataFrame t asbs)- , PrimBytes (DataFrame t as)+ , PrimBytes (DataFrame t bs) , PrimBytes (DataFrame t asbs) ) => SubSpace t (as :: [Nat]) (bs :: [Nat]) (asbs :: [Nat]) where - indexOffset# i l d = case elemSize0 d of- -- if elemSize0 returns 0, then this is a fromScalar-like constructor- 0# -> broadcast (ix# 0# d)- _ -> fromElems (elemOffset d +# i) l (getBytes d) - update ei x df- | I# i <- fromEnum ei- , I# len <- fromIntegral $ totalDim' @asbs- = case runRW#- ( \s0 -> case newByteArray# (len *# byteSize @t undefined) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( writeArray mba i x- ( writeBytes mba 0# df s1 )- )- ) of (# _, r #) -> fromElems 0# len r-- ewmap :: forall s (as' :: [Nat]) (asbs' :: [Nat])- . SubSpace s as' bs asbs'- => (DataFrame s as' -> DataFrame t as)- -> DataFrame s asbs' -> DataFrame t asbs- ewmap f df- | elS <- byteSize @t undefined- , W# lenBSW <- totalDim' @bs- , W# lenASW <- totalDim' @as- , W# lenAS'W <- totalDim' @as'- , lenBS <- word2Int# lenBSW- , lenAS <- word2Int# lenASW- , lenAS' <- word2Int# lenAS'W- , lenASBS <- lenAS *# lenBS- , lenAS'BS <- lenAS' *# lenBS- = case runRW#- ( \s0 -> case newByteArray# (lenASBS *# elS) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( loopWithI# 0# lenAS' lenAS'BS- (\i off -> writeArray mba i (f (indexOffset# off lenAS' df)))- s1- )- ) of (# _, r #) -> fromElems 0# lenASBS r- {-# INLINE ewmap #-}--- iwmap :: forall s (as' :: [Nat]) (asbs' :: [Nat])- . SubSpace s as' bs asbs'- => (Idxs bs -> DataFrame s as' -> DataFrame t as)- -> DataFrame s asbs' -> DataFrame t asbs- iwmap f df- | elS <- byteSize @t undefined- , dbs <- dims @_ @bs- , W# lenBSW <- totalDim dbs- , W# lenASW <- totalDim' @as- , W# lenAS'W <- totalDim' @as'- , lenBS <- word2Int# lenBSW- , lenAS <- word2Int# lenASW- , lenAS' <- word2Int# lenAS'W- , lenASBS <- lenAS *# lenBS- = case runRW#- ( \s0 -> case newByteArray# (lenASBS *# elS) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( overDim_# dbs- ( \i pos ->- writeArray mba pos (f i (indexOffset# (pos *# lenAS') lenAS' df))- ) 0# 1# s1- )- ) of (# _, r #) -> fromElems 0# lenASBS r-- ewgen x = case elemSize0 x of- 0# -> broadcast (ix# 0# x)- 1# -> broadcast (ix# 0# x)- lenAS- | elS <- byteSize @t undefined- , W# lenBSW <- totalDim' @bs- , lenBS <- word2Int# lenBSW- , lenASBS <- lenAS *# lenBS- , bsize <- lenASBS *# elS- -> case runRW#- ( \s0 -> case newByteArray# bsize s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( loop# 0# (lenAS *# elS) bsize- (\off -> writeBytes mba off x)- s1- )- ) of (# _, r #) -> fromElems 0# lenASBS r- {-# INLINE [1] ewgen #-}-- iwgen f- | elS <- byteSize @t undefined- , dbs <- dims @_ @bs- , W# lenBSW <- totalDim dbs- , W# lenASW <- totalDim' @as- , lenBS <- word2Int# lenBSW- , lenAS <- word2Int# lenASW- , lenASBS <- lenAS *# lenBS- = case runRW#- ( \s0 -> case newByteArray# (lenASBS *# elS) s0 of- (# s1, mba #) -> unsafeFreezeByteArray# mba- ( overDim_# dbs- ( \i pos -> writeArray mba pos (f i)- ) 0# 1# s1- )- ) of (# _, r #) -> fromElems 0# lenASBS r-- ewfoldl f x0 df- | ba <- getBytes df- = foldDimOff (dims @_ @bs) (\(I# o) acc -> f acc (fromBytes o ba))- (I# (byteOffset df))- (I# (byteSize @t undefined) * fromIntegral (totalDim' @as)) x0-- iwfoldl f x0 df- | ba <- getBytes df- = foldDim (dims @_ @bs) (\i (I# o) acc -> f i acc (fromBytes o ba))- (I# (byteOffset df))- (I# (byteSize @t undefined) * fromIntegral (totalDim' @as)) x0-- ewfoldr f x0 df- | step <- I# (byteSize @t undefined) * fromIntegral (totalDim' @as)- , ba <- getBytes df- = foldDimOff (dims @_ @bs) (\(I# o) -> f (fromBytes o ba))- (I# (byteOffset df +# byteSize df) - step)- (negate step) x0-- iwfoldr f x0 df- | step <- I# (byteSize @t undefined) * fromIntegral (totalDim' @as)- , ba <- getBytes df- = foldDimReverse (dims @_ @bs) (\i (I# o) -> f i (fromBytes o ba))- (I# (byteOffset df +# byteSize df) - step)- step x0--- -- implement elementWise in terms of indexWise- elementWise = indexWise . const- {-# INLINE elementWise #-}-- indexWise :: forall (s :: Type) (f :: Type -> Type) (as' :: [Nat]) (asbs' :: [Nat])- . ( Applicative f- , SubSpace s as' bs asbs'- )- => (Idxs bs -> DataFrame s as' -> f (DataFrame t as))- -> DataFrame s asbs' -> f (DataFrame t asbs)- indexWise f df = runWithState <$> iwfoldl applyF (pure initialState) df- where- -- run a state-based continuation within RW- runWithState :: ( State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))- -> DataFrame t asbs- runWithState g = case runRW#- ( \s0 -> case g s0 of- (# s1, (# marr, _ #) #) -> unsafeFreezeByteArray# marr s1- ) of (# _, arr #) -> fromElems 0# rezLength# arr-- -- Prepare empty byte array for the result DataFrame and keep a current position counter- -- Input: state- -- Output: state +- -- ( current mutable byte array + current write position )- initialState :: State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #)- initialState s0 = case newByteArray# (rezLength# *# rezElBSize#) s0 of- (# s1, marr #) -> (# s1, (# marr, 0# #) #)-- -- Given the result chunk, write it into a mutable array- updateChunk :: (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))- -> DataFrame t as- -> (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))- updateChunk g dfChunk = case (# byteOffset dfChunk, getBytes dfChunk #) of- (# off#, arr# #) -> \s -> case g s of- (# s1, (# marr#, pos# #) #) -> case- copyByteArray# arr# (off# *# rezElBSize#)- marr# (pos# *# rezElBSize#)- (rezStepN# *# rezElBSize#) s1 of- s2 -> (# s2, (# marr#, pos# +# rezStepN# #) #)-- -- Apply applicative functor on each chunk and update a state.- applyF :: Idxs bs- -> f (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))- -> DataFrame s as'- -> f (State# RealWorld -> (# State# RealWorld, (# MutableByteArray# RealWorld, Int# #) #))- applyF idx s dfChunk = idx `seq` dfChunk `seq` updateChunk <$> s <*> f idx dfChunk-- -- Element byte size of the result DataFrame (byte size of s)- rezElBSize# = byteSize @t undefined- -- Number of primitive elements in the result DataFrame chunk- !(I# rezStepN#) = fromIntegral $ totalDim' @as- -- Number of primitive elements in the result DataFrame- !(I# rezLength#) = fromIntegral $ totalDim' @asbs+dropPref :: Dims (ns :: [Nat]) -> CumulDims -> CumulDims+dropPref ds = CumulDims . drop (length $ listDims ds) . unCumulDims unSc :: DataFrame (t :: Type) ('[] :: [Nat]) -> t
src/Numeric/DataFrame/Type.hs view
@@ -1,464 +1,1140 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UnboxedTuples #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Numeric.DataFrame.Type- ( -- * Data types- DataFrame (..)- , SomeDataFrame (..), DataFrame'- , pattern (:*:), pattern Z- -- * Infer type class instances- , AllTypes, ImplAllows, ArraySingletons, PrimFrames- , DataFrameInference (..)- , inferOrd, inferNum, inferFractional, inferFloating- , inferOrd', inferNum', inferFractional', inferFloating'- , inferASing', inferEq', inferShow', inferPrim', inferPrimElem'- -- * Misc- , ixOff, unsafeFromFlatList- , Dim1 (..), Dim2 (..), Dim3 (..)- , dimSize1, dimSize2, dimSize3- , bSizeOf, bAlignOf- -- * Re-exports from dimensions- , Dim (..), Idx (..), XNat (..), Dims, Idxs, TypedList (..)- ) where---import Data.Proxy (Proxy)-import Foreign.Storable (Storable (..))-import GHC.Base-import GHC.Ptr (Ptr (..))--import Numeric.DataFrame.Family-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.Family (Array, ArraySingleton (..))-import qualified Numeric.DataFrame.Internal.Array.Family as AFam-import Numeric.Dimensions-import Numeric.PrimBytes---- | Single frame-newtype instance DataFrame (t :: Type) (ns :: [Nat])- = SingleFrame { _getDF :: Array t ns }---- | Multiple "columns" of data frames of the same shape-newtype instance DataFrame (ts :: [Type]) (ns :: [Nat])- = MultiFrame { _getDFS :: TypedList (DataFrame' ns) ts }---- | Data frame with some dimensions missing at compile time.--- Pattern-match against its constructor to get a Nat-indexed data frame.-data instance DataFrame (ts :: l) (xns :: [XNat])- = forall (ns :: [Nat])- . (KnownXNatTypes xns, FixedDims xns ns, Dimensions ns, ArraySingletons ts ns)- => XFrame (DataFrame ts ns)---- | Data frame that has an unknown dimensionality at compile time.--- Pattern-match against its constructor to get a Nat-indexed data frame-data SomeDataFrame (t :: l)- = forall (ns :: [Nat]) . (Dimensions ns, ArraySingletons t ns)- => SomeDataFrame (DataFrame t ns)---- | DataFrame with its type arguments swapped.-newtype DataFrame' (xs :: [k]) (t :: l) = DataFrame' (DataFrame t xs)--{-# COMPLETE Z, (:*:) #-}----- | Constructing a @MultiFrame@ using DataFrame columns-pattern (:*:) :: forall (xs :: [Type]) (ns :: [Nat])- . ()- => forall (y :: Type) (ys :: [Type])- . (xs ~ (y ': ys))- => DataFrame y ns- -> DataFrame ys ns -> DataFrame xs ns-pattern (:*:) x xs <- (MultiFrame (DataFrame' x :* (MultiFrame -> xs)))- where- (:*:) x (MultiFrame xs) = MultiFrame (DataFrame' x :* xs)-infixr 6 :*:---- | Empty MultiFrame-pattern Z :: forall (xs :: [Type]) (ns :: [Nat])- . () => (xs ~ '[]) => DataFrame xs ns-pattern Z = MultiFrame U-------------------------------------------------------------------------------------- All Eq instances-----------------------------------------------------------------------------------deriving instance Eq (Array t ds) => Eq (DataFrame (t :: Type) (ds :: [Nat]))--instance ImplAllows Eq ts ds => Eq (DataFrame (ts :: [Type]) ds) where- Z == Z = True- (a :*: as) == (b :*: bs) = a == b && as == bs--instance (AllTypes Eq t, DataFrameInference t)- => Eq (DataFrame (t :: l) (ds :: [XNat])) where- (XFrame dfa) == (XFrame dfb)- | Just E <- sameDims' dfa dfb- , E <- inferEq dfa = dfa == dfb- _ == _ = False--instance (AllTypes Eq t, DataFrameInference t)- => Eq (SomeDataFrame (t :: l)) where- (SomeDataFrame dfa) == (SomeDataFrame dfb)- | Just E <- sameDims' dfa dfb- , E <- inferEq dfa = dfa == dfb- _ == _ = False-------------------------------------------------------------------------------------- All Show instances-----------------------------------------------------------------------------------instance ( Show (Array t ds)- , Dimensions ds- ) => Show (DataFrame (t :: Type) (ds :: [Nat])) where- show (SingleFrame arr) = unlines- [ "DF " ++ drop 5 (show $ dims @_ @ds) ++ ":"- , show arr- ]--instance ( Dimensions ds- , ImplAllows Show ts ds- ) => Show (DataFrame (ts :: [Type]) (ds :: [Nat])) where- show dfs = unlines $- ("DF " ++ show (order dds) ++ " x " ++ drop 5 (show dds) ++ ":")- : showAll 1 dfs- where- dds = dims @_ @ds- showAll :: ImplAllows Show xs ds- => Word -> DataFrame (xs :: [Type]) ds -> [String]- showAll _ Z = []- showAll n (SingleFrame arr :*: fs)- = ("Var " ++ show n) : show arr : showAll (n+1) fs---instance (AllTypes Show t, DataFrameInference t)- => Show (DataFrame (t :: l) (xns :: [XNat])) where- show (XFrame df)- | E <- inferShow df = 'X': show df--instance (AllTypes Show t, DataFrameInference t)- => Show (SomeDataFrame (t :: l)) where- show (SomeDataFrame df)- | E <- inferShow df = "Some" ++ show df--------------------------------------------------------------------------------------type family AllTypes (f :: Type -> Constraint) (ts :: l) :: Constraint where- AllTypes f (t :: Type) = f t- AllTypes f (ts :: [Type]) = All f ts--type family ImplAllows (f :: Type -> Constraint) (ts :: l) (ds :: [Nat])- :: Constraint where- ImplAllows f (t :: Type) ds = f (Array t ds)- ImplAllows _ ('[] :: [Type]) _ = ()- ImplAllows f (t ': ts :: [Type]) ds = (f (Array t ds), ImplAllows f ts ds)--type family ArraySingletons (ts :: l) (ns :: [Nat]) :: Constraint where- ArraySingletons (t :: Type) ns = ArraySingleton t ns- ArraySingletons ('[] :: [Type]) _ = ()- ArraySingletons (t ': ts :: [Type]) ns- = (ArraySingleton t ns, ArraySingletons ts ns)--type family PrimFrames (ts :: l) (ns :: [Nat]) :: Constraint where- PrimFrames (t :: Type) ns- = (PrimBytes (DataFrame t ns), PrimArray t (DataFrame t ns))- PrimFrames ('[] :: [Type]) _ = ()- PrimFrames (t ': ts :: [Type]) ns- = ( PrimBytes (DataFrame t ns), PrimArray t (DataFrame t ns)- , PrimFrames ts ns)---deriving instance Bounded (Array t ds) => Bounded (DataFrame t ds)-deriving instance Enum (Array t ds) => Enum (DataFrame t ds)-deriving instance Integral (Array t ds)- => Integral (DataFrame t ds)-deriving instance Num (Array t ds)- => Num (DataFrame t ds)-deriving instance Fractional (Array t ds)- => Fractional (DataFrame t ds)-deriving instance Floating (Array t ds)- => Floating (DataFrame t ds)-deriving instance Ord (Array t ds)- => Ord (DataFrame t ds)-deriving instance ( Read (Array t ds), Dimensions ds )- => Read (DataFrame t ds)-deriving instance Real (Array t ds)- => Real (DataFrame t ds)-deriving instance RealFrac (Array t ds)- => RealFrac (DataFrame t ds)-deriving instance RealFloat (Array t ds)- => RealFloat (DataFrame t ds)-deriving instance (PrimArray t (Array t ds), PrimBytes t)- => PrimArray t (DataFrame t ds)-deriving instance PrimBytes (Array t ds)- => PrimBytes (DataFrame t ds)----instance PrimBytes (DataFrame t ds) => Storable (DataFrame t ds) where- sizeOf x = I# (byteSize x)- alignment x = I# (byteAlign x)- peek (Ptr addr) = IO (readAddr addr)- poke (Ptr addr) a = IO (\s -> (# writeAddr a addr s, () #))----class DataFrameInference (t :: l) where- -- | Bring an evidence of `ArraySingleton` instance into- -- a scope at runtime.- -- This is often used to let GHC infer other complex type class instances,- -- such as `SubSpace`.- inferASing- :: (AllTypes PrimBytes t, Dimensions ds)- => DataFrame t ds -> Evidence (ArraySingletons t ds)- inferEq- :: (AllTypes Eq t, ArraySingletons t ds)- => DataFrame t ds -> Evidence (Eq (DataFrame t ds))- inferShow- :: (AllTypes Show t, ArraySingletons t ds, Dimensions ds)- => DataFrame t ds -> Evidence (Show (DataFrame t ds))- inferPrim- :: (AllTypes PrimBytes t, ArraySingletons t ds, Dimensions ds)- => DataFrame t ds -> Evidence (PrimFrames t ds)- -- | This is a special function, because Scalar does not require PrimBytes.- -- That is why the dimension list in the argument nust not be empty.- inferPrimElem- :: (ArraySingletons t ds, ds ~ (Head ds ': Tail ds))- => DataFrame t ds -> Evidence (AllTypes PrimBytes t)----instance DataFrameInference (t :: Type) where- inferASing (_ :: DataFrame t ds)- = AFam.inferASing @t @ds- inferEq (_ :: DataFrame t ds)- = case AFam.inferEq @t @ds of E -> E- inferShow (_ :: DataFrame t ds)- = case AFam.inferShow @t @ds of E -> E- inferPrim (_ :: DataFrame t ds)- = case AFam.inferPrim @t @ds of E -> E- inferPrimElem (_ :: DataFrame t ds)- = case AFam.inferPrimElem @t @(Head ds) @(Tail ds) of E -> E--inferOrd' :: forall t ds- . (Ord t, ArraySingleton t ds)- => Evidence (Ord (DataFrame t ds))-inferOrd' = case AFam.inferOrd @t @ds of E -> E--inferNum' :: forall t ds- . (Num t, ArraySingletons t ds)- => Evidence (Num (DataFrame t ds))-inferNum' = case AFam.inferNum @t @ds of E -> E--inferFractional' :: forall t ds- . (Fractional t, ArraySingleton t ds)- => Evidence (Fractional (DataFrame t ds))-inferFractional' = case AFam.inferFractional @t @ds of E -> E--inferFloating' :: forall t ds- . (Floating t, ArraySingleton t ds)- => Evidence (Floating (DataFrame t ds))-inferFloating' = case AFam.inferFloating @t @ds of E -> E---instance RepresentableList ts => DataFrameInference (ts :: [Type]) where- inferASing (_ :: DataFrame t ds)- = inferASings @ts @ds (tList @_ @ts)- inferEq (_ :: DataFrame t ds)- = case inferEqs @ts @ds (tList @_ @ts) of E -> E- inferShow (_ :: DataFrame t ds)- = case inferShows @ts @ds (tList @_ @ts) of E -> E- inferPrim (_ :: DataFrame t ds)- = case inferPrims @ts @ds (tList @_ @ts) of E -> E- inferPrimElem (_ :: DataFrame t ds)- = case inferPrimElems @ts @(Head ds) @(Tail ds) (tList @_ @ts) of E -> E----inferASings :: forall ts ds- . (All PrimBytes ts, Dimensions ds)- => TypeList ts -> Evidence (ArraySingletons ts ds)-inferASings U = E-inferASings ((_ :: Proxy t) :* ts)- = case (inferASing' @t @ds, inferASings @_ @ds ts) of (E, E) -> E----inferEqs :: forall ts ds- . (All Eq ts, ArraySingletons ts ds)- => TypeList ts -> Evidence (ImplAllows Eq ts ds)-inferEqs U = E-inferEqs ((_ :: Proxy t) :* ts)- = case (AFam.inferEq @t @ds, inferEqs @_ @ds ts) of (E, E) -> E--inferShows :: forall ts ds- . (All Show ts, ArraySingletons ts ds, Dimensions ds)- => TypeList ts -> Evidence (ImplAllows Show ts ds)-inferShows U = E-inferShows ((_ :: Proxy t) :* ts)- = case (AFam.inferShow @t @ds, inferShows @_ @ds ts) of (E, E) -> E--inferPrims :: forall ts ds- . (All PrimBytes ts, ArraySingletons ts ds, Dimensions ds)- => TypeList ts -> Evidence (PrimFrames ts ds)-inferPrims U = E-inferPrims ((_ :: Proxy t) :* ts)- = case (AFam.inferPrim @t @ds, inferPrims @_ @ds ts) of (E, E) -> E--inferPrimElems :: forall ts d ds- . (ArraySingletons ts (d ': ds))- => TypeList ts -> Evidence (All PrimBytes ts)-inferPrimElems U = E-inferPrimElems ((_ :: Proxy t) :* ts)- = case (AFam.inferPrimElem @t @d @ds, inferPrimElems @_ @d @ds ts) of (E, E) -> E---inferASing' :: forall t ds- . (DataFrameInference t, AllTypes PrimBytes t, Dimensions ds)- => Evidence (ArraySingletons t ds)-inferASing' = inferASing (undefined :: DataFrame t ds)--inferEq' :: forall t ds- . (DataFrameInference t, AllTypes Eq t, ArraySingletons t ds)- => Evidence (Eq (DataFrame t ds))-inferEq' = inferEq (undefined :: DataFrame t ds)--inferShow' :: forall t ds- . ( DataFrameInference t, AllTypes Show t- , ArraySingletons t ds, Dimensions ds)- => Evidence (Show (DataFrame t ds))-inferShow' = inferShow (undefined :: DataFrame t ds)---inferPrim' :: forall t ds- . ( DataFrameInference t, AllTypes PrimBytes t- , ArraySingletons t ds, Dimensions ds)- => Evidence (PrimFrames t ds)-inferPrim' = inferPrim (undefined :: DataFrame t ds)---inferPrimElem' :: forall t ds- . ( DataFrameInference t, ArraySingletons t ds- , ds ~ (Head ds ': Tail ds))- => Evidence (AllTypes PrimBytes t)-inferPrimElem' = inferPrimElem (undefined :: DataFrame t ds)--inferOrd :: forall t ds- . (Ord t, ArraySingleton t ds)- => DataFrame t ds -> Evidence (Ord (DataFrame t ds))-inferOrd = const (inferOrd' @t @ds)--inferNum :: forall t ds- . (Num t, ArraySingletons t ds)- => DataFrame t ds -> Evidence (Num (DataFrame t ds))-inferNum = const (inferNum' @t @ds)--inferFractional :: forall t ds- . (Fractional t, ArraySingleton t ds)- => DataFrame t ds -> Evidence (Fractional (DataFrame t ds))-inferFractional = const (inferFractional' @t @ds)--inferFloating :: forall t ds- . (Floating t, ArraySingleton t ds)- => DataFrame t ds -> Evidence (Floating (DataFrame t ds))-inferFloating = const (inferFloating' @t @ds)-------------------------------------------------------------------------------------- * Misc------------------------------------------------------------------------------------- | A wrapper on `byteSize`-bSizeOf :: PrimBytes a => a -> Int-bSizeOf a = I# (byteSize a)---- | A wrapper on `byteAlign`-bAlignOf :: PrimBytes a => a -> Int-bAlignOf a = I# (byteAlign a)---- | Number of elements along the 1st dimension.-dimSize1 :: Dim1 t ds => t ds -> Word-dimSize1 = dimVal . dim1---- | Number of elements along the 2nd dimension.-dimSize2 :: Dim2 t ds => t ds -> Word-dimSize2 = dimVal . dim2---- | Number of elements along the 3rd dimension.-dimSize3 :: Dim3 t ds => t ds -> Word-dimSize3 = dimVal . dim3--class Dim1 (t :: [k] -> Type) (ds :: [k]) where- dim1 :: t ds -> Dim (Head ds)--class Dim2 (t :: [k] -> Type) (ds :: [k]) where- dim2 :: t ds -> Dim (Head (Tail ds))--class Dim3 (t :: [k] -> Type) (ds :: [k]) where- dim3 :: t ds -> Dim (Head (Tail (Tail ds)))---instance {-# OVERLAPPABLE #-}- Dimensions (d ': ds)- => Dim1 t (d ': ds :: [k]) where- dim1 _ = case dims @k @(d ': ds) of d :* _ -> d--instance {-# OVERLAPPING #-}- Dim1 (TypedList Dim) (d ': ds) where- dim1 (d :* _) = d--instance {-# OVERLAPPING #-}- Dim1 (DataFrame l) (d ': ds :: [XNat]) where- dim1 (XFrame (_ :: DataFrame l ns))- = case xDims' @(d ': ds) @ns of d :* _ -> d--instance {-# OVERLAPPABLE #-}- Dimensions (d1 ': d2 ': ds)- => Dim2 t (d1 ': d2 ': ds :: [k]) where- dim2 _ = case dims @k @(d1 ': d2 ': ds) of _ :* d :* _ -> d--instance {-# OVERLAPPING #-}- Dim2 (TypedList Dim) (d1 ': d2 ': ds) where- dim2 (_ :* d :* _) = d--instance {-# OVERLAPPING #-}- Dim2 (DataFrame l) (d1 ': d2 ': ds :: [XNat]) where- dim2 (XFrame (_ :: DataFrame l ns))- = case xDims' @(d1 ': d2 ': ds) @ns of _ :* d :* _ -> d--instance {-# OVERLAPPABLE #-}- Dimensions (d1 ': d2 ': d3 ': ds)- => Dim3 t (d1 ': d2 ': d3 ': ds :: [k]) where- dim3 _ = case dims @k @(d1 ': d2 ': d3 ': ds) of _ :* _ :* d :* _ -> d--instance {-# OVERLAPPING #-}- Dim3 (TypedList Dim) (d1 ': d2 ': d3 ': ds) where- dim3 (_ :* _ :* d :* _) = d--instance {-# OVERLAPPING #-}- Dim3 (DataFrame l) (d1 ': d2 ': d3 ': ds :: [XNat]) where- dim3 (XFrame (_ :: DataFrame l ns))- = case xDims' @(d1 ': d2 ': d3 ': ds) @ns of _ :* _ :* d :* _ -> d+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++{- |+ The core @easytensor@ types.+ -}+module Numeric.DataFrame.Type+ ( -- * Data types+ SomeDataFrame (..), DataFrame'+#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)+ , DataFrame (SingleFrame, MultiFrame, XFrame)+ , pattern Z, pattern (:*:)+ , pattern S, pattern DF2, pattern DF3, pattern DF4, pattern DF5+ , pattern DF6, pattern DF7, pattern DF8, pattern DF9+#else+ , DataFrame ( SingleFrame, MultiFrame, XFrame, (:*:), Z+ , S, DF2, DF3, DF4, DF5, DF6, DF7, DF8, DF9)+#endif+ -- * Flexible assembling and disassembling+ , PackDF, packDF, unpackDF+ , appendDF, consDF, snocDF+ , fromFlatList, fromListWithDefault, fromList+ , constrainDF+ -- * Infer type class instances+ , KnownBackend (), DFBackend, KnownBackends+ , InferKnownBackend (..), inferPrimElem+ -- * Re-exports+ , Dim (..), Idx (), XNat (..), N, XN, Dims, Idxs, TypedList (..)+ , PrimBytes (), bSizeOf, bAlignOf, bFieldOffsetOf+ , PrimArray (), ixOff+ ) where+++import Data.Data+import Data.Proxy (Proxy)+import Data.Semigroup hiding (All)+import Data.Type.Lits+import Data.Void+import Foreign.Storable (Storable (..))+import GHC.Base+import GHC.Exts (TYPE)+import qualified GHC.Generics as G+import GHC.Ptr (Ptr (..))+import qualified Text.ParserCombinators.ReadPrec as Read+import qualified Text.Read as Read+import qualified Text.Read.Lex as Read++import Numeric.DataFrame.Internal.PrimArray+import Numeric.Dimensions+import Numeric.PrimBytes+import Numeric.ProductOrd+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial+import Numeric.TypedList (typeables)++import {-# SOURCE #-} Numeric.DataFrame.Internal.Backend (DFBackend,+ KnownBackend)+import {-# SOURCE #-} qualified Numeric.DataFrame.Internal.Backend as Backend+import Numeric.DataFrame.Internal.BackendI ()+++-- | Keep data in a primitive data frame+-- and maintain information about Dimensions in the type system+data family DataFrame (t :: l) (xs :: [k])++-- | Single frame+newtype instance DataFrame (t :: Type) (ns :: [Nat])+ = SingleFrame { getSingleFrame :: DFBackend t ns }++-- | Multiple "columns" of data frames of the same shape+newtype instance DataFrame (ts :: [Type]) (ns :: [Nat])+ = MultiFrame ( TypedList (DataFrame' ns) ts )++-- | Data frame with some dimensions missing at compile time.+-- Pattern-match against its constructor to get a Nat-indexed data frame.+data instance DataFrame (ts :: l) (xns :: [XNat])+ = forall (ns :: [Nat])+ . (KnownXNatTypes xns, FixedDims xns ns, Dimensions ns, KnownBackends ts ns)+ => XFrame (DataFrame ts ns)++-- | Data frame that has an unknown dimensionality at compile time.+-- Pattern-match against its constructor to get a Nat-indexed data frame+data SomeDataFrame (t :: l)+ = forall (ns :: [Nat]) . (Dimensions ns, KnownBackends t ns)+ => SomeDataFrame (DataFrame t ns)+ deriving Typeable++-- | DataFrame with its type arguments swapped.+newtype DataFrame' (xs :: [k]) (t :: l) = DataFrame' (DataFrame t xs)+ deriving Typeable++{-# COMPLETE Z, (:*:) #-}+++-- | Constructing a @MultiFrame@ using DataFrame columns+pattern (:*:) :: forall (xs :: [Type]) (ns :: [Nat]) . ()+ => forall (y :: Type) (ys :: [Type]) . (xs ~ (y ': ys))+ => DataFrame y ns -> DataFrame ys ns -> DataFrame xs ns+pattern (:*:) x xs <- (MultiFrame (DataFrame' x :* (MultiFrame -> xs)))+ where+ (:*:) x (MultiFrame xs) = MultiFrame (DataFrame' x :* xs)+infixr 6 :*:++-- | Empty MultiFrame+pattern Z :: forall (xs :: [Type]) (ns :: [Nat])+ . () => (xs ~ '[]) => DataFrame xs ns+pattern Z = MultiFrame U++-- | I use this kind-polymorphic constraint to generalize @XFrame@ and @SomeDataFrame@+-- over @SingleFrame@ and @MultiFrame@.+type family KnownBackends (ts :: l) (ns :: [Nat]) :: Constraint where+ KnownBackends ( t :: Type ) ns = KnownBackend t ns+ KnownBackends ('[] :: [Type]) _ = ()+ KnownBackends (t ': ts :: [Type]) ns =+ (KnownBackend t ns, KnownBackends ts ns)++-- | Allow inferring @KnownBackends@ if you know the dimensions and the element types.+class InferKnownBackend (t :: k) ds where+ -- Infer @KnownBackends@ if you know the dimensions and the element types.+ inferKnownBackend :: Dict (KnownBackends t ds)++instance (PrimBytes t, Dimensions ds) => InferKnownBackend (t :: Type) ds where+ inferKnownBackend = Backend.inferKnownBackend @t @ds++instance (RepresentableList ts, All PrimBytes ts, Dimensions ds)+ => InferKnownBackend (ts :: [Type]) ds where+ inferKnownBackend = go (tList @_ @ts)+ where+ go :: forall ss . All PrimBytes ss => TypeList ss -> Dict (KnownBackends ss ds)+ go U = Dict+ go ((_ :: Proxy t) :* ts)+ = case Backend.inferKnownBackend @t @ds of+ Dict -> case go ts of+ Dict -> Dict++-- | All component data frames must satisfy a given constraint.+type family AllFrames (f :: Type -> Constraint) (ts :: [Type]) (ds :: [Nat])+ :: Constraint where+ AllFrames _ '[] _ = ()+ AllFrames f (t ': ts) ds = (f (DataFrame t ds), AllFrames f ts ds)+++deriving instance Typeable (DataFrame (t :: l) (xs :: [k]))+deriving instance ( Data (DataFrame t xs)+ , Typeable t, Typeable xs, Typeable k, Typeable l)+ => Data (DataFrame' (xs :: [k]) (t :: l))+deriving instance Eq (DFBackend t ds)+ => Eq (DataFrame t ds)+deriving instance Ord (DFBackend t ds)+ => Ord (DataFrame t ds)+deriving instance ProductOrder (DFBackend t ds)+ => ProductOrder (DataFrame t ds)+deriving instance Bounded (DFBackend t ds)+ => Bounded (DataFrame t ds)+deriving instance Enum (DFBackend t ds)+ => Enum (DataFrame t ds)+deriving instance Integral (DFBackend t ds)+ => Integral (DataFrame t ds)+deriving instance Num (DFBackend t ds)+ => Num (DataFrame t ds)+deriving instance Fractional (DFBackend t ds)+ => Fractional (DataFrame t ds)+deriving instance Floating (DFBackend t ds)+ => Floating (DataFrame t ds)+deriving instance Real (DFBackend t ds)+ => Real (DataFrame t ds)+deriving instance RealFrac (DFBackend t ds)+ => RealFrac (DataFrame t ds)+deriving instance RealFloat (DFBackend t ds)+ => RealFloat (DataFrame t ds)+deriving instance PrimBytes (DFBackend t ds)+ => PrimBytes (DataFrame t ds)+deriving instance (PrimArray t (DFBackend t ds), PrimBytes t)+ => PrimArray t (DataFrame t ds)++instance Ord (NonTransitive.ProductOrd (DFBackend t ds))+ => Ord (NonTransitive.ProductOrd (DataFrame t ds)) where+ (>) = coerce ((>) @(NonTransitive.ProductOrd (DFBackend t ds)))+ (<) = coerce ((<) @(NonTransitive.ProductOrd (DFBackend t ds)))+ (>=) = coerce ((>=) @(NonTransitive.ProductOrd (DFBackend t ds)))+ (<=) = coerce ((<=) @(NonTransitive.ProductOrd (DFBackend t ds)))+ compare = coerce (compare @(NonTransitive.ProductOrd (DFBackend t ds)))+ min = coerce (min @(NonTransitive.ProductOrd (DFBackend t ds)))+ max = coerce (max @(NonTransitive.ProductOrd (DFBackend t ds)))++instance (Ord (Partial.ProductOrd (DFBackend t ds)), Eq (DFBackend t ds))+ => Ord (Partial.ProductOrd (DataFrame t ds)) where+ (>) = coerce ((>) @(Partial.ProductOrd (DFBackend t ds)))+ (<) = coerce ((<) @(Partial.ProductOrd (DFBackend t ds)))+ (>=) = coerce ((>=) @(Partial.ProductOrd (DFBackend t ds)))+ (<=) = coerce ((<=) @(Partial.ProductOrd (DFBackend t ds)))+ compare = coerce (compare @(Partial.ProductOrd (DFBackend t ds)))+ min = coerce (min @(Partial.ProductOrd (DFBackend t ds)))+ max = coerce (max @(Partial.ProductOrd (DFBackend t ds)))++++instance PrimBytes (DataFrame t ds) => Storable (DataFrame t ds) where+ sizeOf x = I# (byteSize x)+ alignment x = I# (byteAlign x)+ peek (Ptr addr) = IO (readAddr addr)+ poke (Ptr addr) a = IO (\s -> (# writeAddr a addr s, () #))+++instance AllFrames Eq ts ds => Eq (DataFrame (ts :: [Type]) ds) where+ Z == Z = True+ (a :*: as) == (b :*: bs) = a == b && as == bs++instance Eq t => Eq (DataFrame (t :: Type) (ds :: [XNat])) where+ XFrame dfa == XFrame dfb+ | Just Dict <- sameDims' dfa dfb = dfa == dfb+ | otherwise = False++instance All Eq ts => Eq (DataFrame (ts :: [Type]) (ds :: [XNat])) where+ XFrame dfa == XFrame dfb+ | Just Dict <- sameDims' dfa dfb = eqFrames dfa dfb+ | otherwise = False++instance Eq t => Eq (SomeDataFrame (t :: Type)) where+ SomeDataFrame dfa == SomeDataFrame dfb+ | Just Dict <- sameDims' dfa dfb = dfa == dfb+ | otherwise = False++instance All Eq ts => Eq (SomeDataFrame (ts :: [Type])) where+ SomeDataFrame dfa == SomeDataFrame dfb+ | Just Dict <- sameDims' dfa dfb = eqFrames dfa dfb+ | otherwise = False+++eqFrames :: forall (xs :: [Type]) (ns :: [Nat])+ . (KnownBackends xs ns, All Eq xs)+ => DataFrame xs ns -> DataFrame xs ns -> Bool+eqFrames Z Z = True+eqFrames (a :*: as) (b :*: bs) = a == b && eqFrames as bs++++instance ( Show t+ , PrimBytes t+ , Dimensions ds+ ) => Show (DataFrame (t :: Type) (ds :: [Nat])) where+ showsPrec p x = case dims @ds of+ U -> showParen (p >= 10)+ $ showString "S " . showsPrec 10 (unsafeCoerce# x :: t)+ D0 :* _ -> showString "DF0"+ d :* _ -> showParen (p >= 10)+ $ unpackDF' ( \Dict f ->+ let g :: Endo (Int -> ShowS)+ g = Endo $ \k -> f (\o e -> k o . showChar ' ' . showsPrec 11 e)+ n = dimVal d+ in appEndo (stimes n g) (const $ showString "DF" . shows n)+ ) x++instance ( All Show ts+ , All PrimBytes ts+ , Dimensions ds+ ) => Show (DataFrame (ts :: [Type]) (ds :: [Nat])) where+ showsPrec _ Z = showChar 'Z'+ showsPrec p (x :*: xs) = showParen (p >= 7) $+ showsPrec 7 x . showString " :*: " . showsPrec 6 xs++instance (Show t, PrimBytes t)+ => Show (DataFrame (t :: Type) (xns :: [XNat])) where+ showsPrec p (XFrame x)+ = showParen (p >= 10) $ showString "XFrame " . showsPrec 11 x++instance (All Show ts, All PrimBytes ts)+ => Show (DataFrame (ts :: [Type]) (xns :: [XNat])) where+ showsPrec p (XFrame x)+ = showParen (p >= 10) $ showString "XFrame " . showsPrec 11 x++instance (Show t, PrimBytes t)+ => Show (SomeDataFrame (t :: Type)) where+ showsPrec p (SomeDataFrame x)+ = showParen (p >= 10) $ showString "SomeDataFrame " . showsPrec 11 x++instance (All Show ts, All PrimBytes ts)+ => Show (SomeDataFrame (ts :: [Type])) where+ showsPrec p (SomeDataFrame x)+ = showParen (p >= 10) $ showString "SomeDataFrame " . showsPrec 11 x+++instance (Read t, PrimBytes t, Dimensions ds)+ => Read (DataFrame (t :: Type) (ds :: [Nat])) where+ readPrec = readPrecFixedDF (dims @ds)+ readList = Read.readListDefault+ readListPrec = Read.readListPrecDefault++instance (All Read ts, All PrimBytes ts, RepresentableList ts, Dimensions ds)+ => Read (DataFrame (ts :: [Type]) (ds :: [Nat])) where+ readPrec = readFixedMultiDF (tList @Type @ts) (dims @ds)+ readList = Read.readListDefault+ readListPrec = Read.readListPrecDefault++instance (Read t, PrimBytes t, BoundedDims ds, All KnownXNatType ds)+ => Read (DataFrame (t :: Type) (ds :: [XNat])) where+ readPrec = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect $ Read.Ident "XFrame"+ Read.step $ readPrecBoundedDF (minDims @XNat @ds)+ readList = Read.readListDefault+ readListPrec = Read.readListPrecDefault++instance ( All Read ts, All PrimBytes ts, RepresentableList ts+ , BoundedDims ds, All KnownXNatType ds)+ => Read (DataFrame (ts :: [Type]) (ds :: [XNat])) where+ readPrec = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect $ Read.Ident "XFrame"+ Read.step $ readBoundedMultiDF (tList @Type @ts) (minDims @XNat @ds)+ readList = Read.readListDefault+ readListPrec = Read.readListPrecDefault++instance (Read t, PrimBytes t)+ => Read (SomeDataFrame (t :: Type)) where+ readPrec = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect $ Read.Ident "SomeDataFrame"+ Read.step readPrecSomeDF+ readList = Read.readListDefault+ readListPrec = Read.readListPrecDefault++instance ( All Read ts, All PrimBytes ts, RepresentableList ts )+ => Read (SomeDataFrame (ts :: [Type])) where+ readPrec = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect $ Read.Ident "SomeDataFrame"+ Read.step $ readSomeMultiDF (tList @Type @ts)+ readList = Read.readListDefault+ readListPrec = Read.readListPrecDefault++readPrecFixedDF :: forall (t :: Type) (ds :: [Nat])+ . (Read t, PrimBytes t)+ => Dims ds -> Read.ReadPrec (DataFrame t ds)+readPrecFixedDF U+ = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect $ Read.Ident "S"+ S <$> Read.step Read.readPrec+readPrecFixedDF (D0 :* Dims)+ = Read.parens $ do+ Read.lift . Read.expect . Read.Ident $ "DF0"+ return (packDF @t @0)+readPrecFixedDF (d@D :* ds@Dims)+ = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect . Read.Ident $ "DF" ++ show (dimVal d)+ packDF' (<*> Read.step (readPrecFixedDF ds)) pure++{-+The first argument is, in fact, a @dimsBound@, but covered in the same @[XNat]@+ form. That is, XN values are lower bounds rather than actual runtime dimensions.++The interesting bit about this function is that it is very particular in specifying+what is enforced and what is unknown.+At the very least, the call site must know the order of the Dims (unless DF0 is present)+ -- and specify all dims as @XN 0@.+It allows a fine-grained control over the shape of a DataFrame.++For example,++>>> readPrecBoundedDF (Dx @5 DF5 :* Dn DF4 :* Dn DF4 :* U)++ reads an array of 4x4 matrices of length at least 5.++ -}+readPrecBoundedDF :: forall (t :: Type) (ds :: [XNat])+ . (Read t, PrimBytes t, KnownXNatTypes ds)+ => Dims ds -> Read.ReadPrec (DataFrame t ds)+-- reading scalar+readPrecBoundedDF U+ = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect $ Read.Ident "S"+ case inferKnownBackend @t @'[] of+ Dict -> XFrame . S <$> Read.step Read.readPrec+-- DF0 is funny because it will succesfully parse any dimension to the right of it.+readPrecBoundedDF (Dn D0 :* XDims (Dims :: Dims ns))+ = Read.parens $ do+ Read.lift . Read.expect . Read.Ident $ "DF0"+ return $ case inferKnownBackend @t @(0 ': ns) of+ Dict -> XFrame @Type @t @ds @(0 ': ns) (packDF @t @0 @ns)+-- Fixed dimension:+-- The number of component frames is exactly n+-- the first component frame fixes the shape of the rest n-1+readPrecBoundedDF (Dn d@(D :: Dim n) :* xns)+ = Read.parens . Read.prec 10 $ do+ Read.lift . Read.expect . Read.Ident $ "DF" ++ show (dimVal d)+ XFrame (x :: DataFrame t ns) <- Read.step $ readPrecBoundedDF @t xns+ case inferKnownBackend @t @(n ': ns) of+ Dict -> fmap XFrame . snd . runDelay $ packDF' @t @n @ns+ (readDelayed $ Read.prec 10 (readPrecFixedDF @t @ns dims))+ (followedBy x)+-- Bounded dimension:+-- The number of component frames is at least m+-- the first component frame fixes the shape of the rest n-1+readPrecBoundedDF ((Dx (m :: Dim m) :: Dim xm) :* xns)+ | Dict <- unsafeEqTypes @XNat @('XN m) @xm -- by user contract the argument is dimBound+ = Read.parens $ lookLex >>= \case+ Read.Ident ('D':'F':s)+ | Just (Dx (n :: Dim n)) <- (Read.readMaybe ('D':s) :: Maybe SomeDim)+ , Just Dict <- indeedLE m n -- check if the DF dim is not less than m+ -> case n of+ D0 -> do -- need to repack it under different constraint dims+ XFrame x <- readPrecBoundedDF @t (Dn D0 :* xns)+ return (XFrame x)+ D -> do+ Read.lift . Read.expect . Read.Ident $ "DF" ++ show (dimVal n)+ XFrame (x :: DataFrame t ns) <- Read.prec 10 $ readPrecBoundedDF @t xns+ case inferKnownBackend @t @(n ': ns) of+ Dict -> fmap XFrame . snd . runDelay $ packDF' @t @n @ns+ (readDelayed $ Read.prec 10 (readPrecFixedDF @t @ns dims))+ (followedBy x)++ _ -> Read.pfail+ where+ indeedLE :: forall (a ::Nat) (b :: Nat) . Dim a -> Dim b -> Maybe (Dict (a <= b))+ indeedLE a b = case compareDim a b of+ SLT -> Just Dict+ SEQ -> Just Dict+ SGT -> Nothing++{-+In this case we know Nothing about the dimensionality of a DataFrame.+The logic is similar to readPrecBoundedDF, but a bit simpler:+the first dimension is flexible, but fixes the rest dimensions.+ -}+readPrecSomeDF :: forall (t :: Type) . (Read t, PrimBytes t)+ => Read.ReadPrec (SomeDataFrame t)+readPrecSomeDF = Read.parens $+ Read.prec 10 (do+ Read.lift . Read.expect $ Read.Ident "S"+ case inferKnownBackend @t @'[] of+ Dict -> SomeDataFrame . S <$> Read.readPrec+ )+ Read.++++ (lookLex >>= \case+ Read.Ident ('D':'F':s)+ | Just (Dx (d :: Dim d)) <- (Read.readMaybe ('D':s) :: Maybe SomeDim)+ -> case d of+ D0 | Dict <- inferKnownBackend @t @'[0]+ -> SomeDataFrame <$> readPrecFixedDF @t (D0 :* U)+ _ -> do+ Read.lift . Read.expect . Read.Ident $ "DF" ++ show (dimVal d)+ SomeDataFrame (x :: DataFrame t ds) <- Read.prec 10 $ readPrecSomeDF @t+ case inferKnownBackend @t @(d ': ds) of+ Dict -> fmap SomeDataFrame . snd . runDelay $ packDF' @t @d @ds+ (readDelayed $ Read.prec 10 (readPrecFixedDF @t @ds dims))+ (followedBy x)+ _ -> Read.pfail+ )++readFixedMultiDF :: forall (ts :: [Type]) (ds :: [Nat])+ . (All Read ts, All PrimBytes ts)+ => TypeList ts+ -> Dims ds+ -> Read.ReadPrec (DataFrame ts ds)+readFixedMultiDF U _ = Read.parens $+ Z <$ Read.lift (Read.expect $ Read.Ident "Z")+readFixedMultiDF (_ :* ts) ds = Read.parens . Read.prec 6 $ do+ x <- Read.step $ readPrecFixedDF ds+ Read.lift . Read.expect $ Read.Symbol ":*:"+ xs <- readFixedMultiDF ts ds+ return (x :*: xs)++readBoundedMultiDF :: forall (ts :: [Type]) (ds :: [XNat])+ . (All Read ts, All PrimBytes ts, KnownXNatTypes ds)+ => TypeList ts+ -> Dims ds+ -> Read.ReadPrec (DataFrame ts ds)+readBoundedMultiDF U (XDims (Dims :: Dims ns))+ = Read.parens $+ XFrame @[Type] @'[] @ds @ns Z <$ Read.lift (Read.expect $ Read.Ident "Z")+readBoundedMultiDF ((_ :: Proxy t) :* ts@TypeList) ds+ = Read.parens . Read.prec 6 $ do+ XFrame (x :: DataFrame t ns) <- Read.step $ readPrecBoundedDF @t ds+ Read.lift . Read.expect $ Read.Symbol ":*:"+ xs <- readFixedMultiDF ts (dims @ns)+ case inferKnownBackend @ts @ns of+ Dict -> return $ XFrame (x :*: xs)++readSomeMultiDF :: forall (ts :: [Type])+ . (All Read ts, All PrimBytes ts)+ => TypeList ts+ -> Read.ReadPrec (SomeDataFrame ts)+readSomeMultiDF U+ = Read.parens $+ SomeDataFrame @[Type] @ts @'[] Z <$ Read.lift (Read.expect $ Read.Ident "Z")+readSomeMultiDF ((_ :: Proxy t) :* ts@TypeList)+ = Read.parens . Read.prec 6 $ do+ SomeDataFrame (x :: DataFrame t ns) <- Read.step $ readPrecSomeDF @t+ Read.lift . Read.expect $ Read.Symbol ":*:"+ xs <- readFixedMultiDF ts (dims @ns)+ case inferKnownBackend @ts @ns of+ Dict -> return $ SomeDataFrame (x :*: xs)++-- First element is read separately, enforcing the structure of the rest.+newtype Delayed t ds c a = Delayed { runDelay :: (c (DataFrame t ds), c a) }++followedBy :: Applicative c => DataFrame t ds -> a -> Delayed t ds c a+followedBy x = Delayed . (,) (pure x) . pure++readDelayed :: forall (t :: Type) (ds :: [Nat]) (c :: Type -> Type) (r :: Type)+ . Applicative c+ => c (DataFrame t ds)+ -> Delayed t ds c (DataFrame t ds -> r) -> Delayed t ds c r+readDelayed readF (Delayed (cprev, cf)) = Delayed (readF, cf <*> cprev)+++-- | Check the next lexeme without consuming it+lookLex :: Read.ReadPrec Read.Lexeme+lookLex = Read.look >>=+ Read.choice . map (pure . fst) . Read.readPrec_to_S Read.lexP 10+++++-- | Evidence that the elements of the DataFrame are PrimBytes.+inferPrimElem+ :: forall (t :: Type) (d :: Nat) (ds :: [Nat])+ . KnownBackend t (d ': ds)+ => DataFrame t (d ': ds) -> Dict (PrimBytes t)+inferPrimElem = Backend.inferPrimElem . getSingleFrame++-- | Construct a DataFrame from a flat list.+--+-- The values are filled according to the DataFrame layout: row-by-row and+-- further from the last dimension (least significant) to the first dimension+-- (most significant).+--+-- If the argument list is shorter than @totalDim@, then the rest of the frame+-- is padded with a default value (second argument).+--+-- If the argument list is longer than @totalDim@, then unused values are dropped.+-- If you want, you can pass an infinite list as an argument, i.e. the following+-- is a valid use:+--+-- >>> fromFlatList (dims :: Dims '[2,5]) 0 [6,8..]+--+fromFlatList :: forall (t :: Type) (ds :: [Nat])+ . PrimArray t (DataFrame t ds)+ => Dims ds -> t -> [t] -> DataFrame t ds+fromFlatList = unsafeFromFlatList++++-- | A scalar DataFrame is just a newtype wrapper on a value.+pattern S :: forall (t :: Type) . t -> DataFrame t ('[] :: [Nat])+-- rely on that Scalar is just two times newtype alias to t+pattern S x <- (unsafeCoerce# -> x)+ where+ S = unsafeCoerce#+{-# COMPLETE S #-}+++pattern DF2 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (2 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t (2 ': ds)+pattern DF2 a1 a2+ <- (unpackDF @t @2 @ds (#,,#) -> (# a1,a2,Dict #))+ where DF2 = packDF @t @2 @ds+{-# COMPLETE DF2 #-}++pattern DF3 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (3 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t (3 ': ds)+pattern DF3 a1 a2 a3+ <- (unpackDF @t @3 @ds (#,,,#) -> (# a1,a2,a3,Dict #))+ where DF3 = packDF @t @3 @ds+{-# COMPLETE DF3 #-}++pattern DF4 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (4 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t (4 ': ds)+pattern DF4 a1 a2 a3 a4+ <- (unpackDF @t @4 @ds (#,,,,#) -> (# a1,a2,a3,a4,Dict #))+ where DF4 = packDF @t @4 @ds+{-# COMPLETE DF4 #-}++pattern DF5 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (5 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t ds+ -> DataFrame t (5 ': ds)+pattern DF5 a1 a2 a3 a4 a5+ <- (unpackDF @t @5 @ds (#,,,,,#) -> (# a1,a2,a3,a4,a5,Dict #))+ where DF5 = packDF @t @5 @ds+{-# COMPLETE DF5 #-}++pattern DF6 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (6 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t (6 ': ds)+pattern DF6 a1 a2 a3 a4 a5 a6+ <- (unpackDF @t @6 @ds (#,,,,,,#) -> (# a1,a2,a3,a4,a5,a6,Dict #))+ where DF6 = packDF @t @6 @ds+{-# COMPLETE DF6 #-}++pattern DF7 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (7 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t (7 ': ds)+pattern DF7 a1 a2 a3 a4 a5 a6 a7+ <- (unpackDF @t @7 @ds (#,,,,,,,#) -> (# a1,a2,a3,a4,a5,a6,a7,Dict #))+ where DF7 = packDF @t @7 @ds+{-# COMPLETE DF7 #-}++pattern DF8 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (8 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t (8 ': ds)+pattern DF8 a1 a2 a3 a4 a5 a6 a7 a8+ <- (unpackDF @t @8 @ds (#,,,,,,,,#) -> (# a1,a2,a3,a4,a5,a6,a7,a8,Dict #))+ where DF8 = packDF @t @8 @ds+{-# COMPLETE DF8 #-}++pattern DF9 :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions (9 ': ds))+ => (Dimensions ds, KnownBackend t ds)+ => DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds -> DataFrame t ds+ -> DataFrame t ds+ -> DataFrame t (9 ': ds)+pattern DF9 a1 a2 a3 a4 a5 a6 a7 a8 a9+ <- (unpackDF @t @9 @ds (#,,,,,,,,,#) -> (# a1,a2,a3,a4,a5,a6,a7,a8,a9,Dict #))+ where DF9 = packDF @t @9 @ds+{-# COMPLETE DF9 #-}+++-- | Represent smart constructor functions `packDF` and `unpackDF`.+type family PackDF (t :: Type) (ds :: [Nat]) (d :: Nat) (r :: Type) :: Type where+ PackDF _ _ 0 r = r+ PackDF t ds d r = DataFrame t ds -> PackDF t ds (d - 1) r++{- |+ Takes @d@ arguments of type @DataFrame t ds@ and produce a @DataFrame t (d ': ds)@.++ NB: always use @TypeApplications@ extension with this function to apply all+ type arguments!+ Otherwise, a very dumb type family @PackDF@ will not infer the types for you.++ The following example creates a @Matrix Double 12 3@ filled with twelve+ 3D vectors (using @fromInteger@ of @Vector Double 3@):++ >>> packDF @Double @12 @'[3] 1 2 3 4 5 6 7 8 9 10 11 12++ `packDF` and `unpackDF` together serve as a generic constructor for a DataFrame+ of an arbitrary (statically known) size.++ -}+packDF :: forall (t :: Type) (d :: Nat) (ds :: [Nat])+ . (PrimBytes t, Dimensions (d ': ds))+ => PackDF t ds d (DataFrame t (d ': ds))+packDF+ | d :* Dims <- dims @(d ': ds)+ , Dict <- inferKnownBackend @t @(d ': ds)+ , Dict <- inferKnownBackend @t @ds+ = go d+ | otherwise = error "Numeric.DataFrame.Type.packDF: impossible args"+ where+ go :: (Dimensions ds, KnownBackend t ds, KnownBackend t (d ': ds))+ => Dim d+ -> PackDF t ds d (DataFrame t (d ': ds))+ go d = recur d getResult+ where+ -- number of elements in the frame as Int#+ els = case dimVal d of W# w -> word2Int# w+ -- size of a single element in bytes+ asize = byteSize @(DataFrame t ds) undefined++ getResult :: forall rRep (r :: TYPE rRep)+ . (forall s. Int# -> MutableByteArray# s -> State# s -> r)+ -> r+ getResult f = runRW#+ ( \s0 -> case newByteArray# (asize *# els) s0 of+ (# s1, mba #) -> f 0# mba s1+ )++ recur :: forall n . Dim n+ -> (forall rRep (r :: TYPE rRep)+ . (forall s. Int# -> MutableByteArray# s -> State# s -> r ) -> r)+ -> PackDF t ds n (DataFrame t (d ': ds))+ recur n f = case minusDimM n (D :: Dim 1) of+ Nothing -> case unsafeEqTypes @Nat @n @0 of+ Dict -> f (\_ mba s -> case unsafeFreezeByteArray# mba s of+ (# _, ba #) -> fromBytes 0# ba )+ Just n' -> case unsafeEqTypes @_+ @(PackDF t ds n (DataFrame t (d ': ds)))+ @(DataFrame t ds -> PackDF t ds (n - 1) (DataFrame t (d ': ds))) of+ Dict -> \x -> recur n'+ ( \c -> f (\off mba s -> c (off +# asize) mba (writeBytes mba off x s)) )++++{- |+ Takes a function (e.g. a constructor) with @d+1@ argument (df1, df2, .. dfd, Dict)+ and a @DataFrame t (d ': ds)@.+ Feeds the dataframe elements into that function.+ For example, you can pass a tuple to this function, and get all dataframe elements+ (and some dictionaries -- useful evidence to work with element frames)++ NB: always use @TypeApplications@ extension with this function to apply all+ type arguments!+ Otherwise, a very dumb type family @PackDF@ will not infer the types for you.++ The following example unpacks a 3D vector+ (created using @fromInteger@ of @Vector Double 3@)+ into a 4-tuple with three scalars and one Dict:++ >>> unpackDF @Double @3 @'[] (,,,) 2++ `packDF` and `unpackDF` together serve as a generic constructor for a DataFrame+ of an arbitrary (statically known) size.++ -}+unpackDF :: forall (t :: Type) (d :: Nat) (ds :: [Nat])+ (rep :: RuntimeRep) (r :: TYPE rep)+ . (PrimBytes t, Dimensions (d ': ds))+ => PackDF t ds d (Dict (Dimensions ds, KnownBackend t ds) -> r)+ -> DataFrame t (d ': ds) -> r+unpackDF c+ | d :* Dims <- dims @(d ': ds)+ = unpackDF' (go d)+ | otherwise = error "Numeric.DataFrame.Type.unpackDF: impossible args"+ where+ go :: forall a . (a ~ Dict (Dimensions ds, KnownBackend t ds))+ => Dim d -> a+ -> (forall (zRep :: RuntimeRep) (z :: TYPE zRep)+ . (Int -> DataFrame t ds -> z) -> Int -> z)+ -> Int -> r+ go d a k = recur d (const c)+ where+ recur :: forall n+ . Dim n+ -> (Int -> PackDF t ds n (a -> r))+ -> Int -> r+ recur n f = case minusDimM n (D :: Dim 1) of+ Nothing -> case unsafeEqTypes @Nat @n @0 of+ Dict -> (`f` a)+ Just n' -> case unsafeEqTypes @_+ @(PackDF t ds n (a -> r))+ @(DataFrame t ds -> PackDF t ds (n - 1) (a -> r)) of+ Dict -> recur n' (k f)+++packDF' :: forall (t :: Type) (d :: Nat) (ds :: [Nat]) c+ . (PrimBytes t, Dimensions (d ': ds))+ => (forall r. c (DataFrame t ds -> r) -> c r)+ -> (forall r. r -> c r)+ -> c (DataFrame t (d ': ds))+packDF' k z+ | d :* _ <- dims @(d ': ds)+ = go d (z (packDF @t @d @ds))+ | otherwise = error "Numeric.DataFrame.Type.packDF': impossible args"+ where+ go :: forall n . Dim n+ -> c (PackDF t ds n (DataFrame t (d ': ds))) -> c (DataFrame t (d ': ds))+ go n = case minusDimM n (D :: Dim 1) of+ Nothing -> case unsafeEqTypes @Nat @n @0 of Dict -> id+ Just n' -> case unsafeEqTypes @_+ @(PackDF t ds n (DataFrame t (d ': ds)))+ @(DataFrame t ds -> PackDF t ds (n - 1) (DataFrame t (d ': ds))) of+ Dict -> go n' . k+++-- Parameter Int# here is an element offset, it should not be used at the call site.+unpackDF' :: forall (rep :: RuntimeRep)+ (t :: Type) (d :: Nat) (ds :: [Nat]) (r :: TYPE rep)+ . (PrimBytes t, Dimensions (d ': ds))+ => ( Dict (Dimensions ds, KnownBackend t ds)+ -> (forall (zRep :: RuntimeRep) (z :: TYPE zRep)+ . (Int -> DataFrame t ds -> z) -> Int -> z)+ -> Int -> r)+ -> DataFrame t (d ': ds)+ -> r+unpackDF' k df+ | d :* Dims <- dims @(d ': ds)+ , Dict <- inferKnownBackend @t @(d ': ds)+ , Dict <- inferKnownBackend @t @ds+ = case arrayContent# df of+ (# x | #)+ | e <- broadcast x+ -> let f :: forall (zr :: RuntimeRep) (z :: TYPE zr)+ . (Int -> DataFrame t ds -> z) -> Int -> z+ f consume = (`consume` e)+ in k Dict f 0+ (# | (# cdims, off, arr #) #)+ | cd <- CumulDims . tail $ unCumulDims cdims+ , td <- cdTotalDim# cd+ , n <- case dimVal d of W# w -> word2Int# w+ -> let f :: forall (zr :: RuntimeRep) (z :: TYPE zr)+ . (Int -> DataFrame t ds -> z) -> Int -> z+ f consume (I# o) = consume (I# (o -# td)) (fromElems cd o arr)+ in k Dict f (I# (off +# td *# (n -# 1#)))+ | otherwise = error "Numeric.DataFrame.Type.unpackDF: impossible args"+++-- | Append one DataFrame to another, sum up the first dimension.+--+-- If you want to deconstruct a DataFrame, use+-- `Numeric.DataFrame.SubSpace.index`+-- or `Numeric.DataFrame.SubSpace.slice` instead.+appendDF :: forall (n :: Nat) (m :: Nat) (ds :: [Nat]) (t :: Type)+ . ( PrimBytes t, Dimensions ds, KnownDim n, KnownDim m )+ => DataFrame t (n :+ ds)+ -> DataFrame t (m :+ ds)+ -> DataFrame t ((n + m) :+ ds)+appendDF+ | D <- D @n `plusDim` D @m+ , Dict <- inferKnownBackend @t @(n :+ ds)+ , Dict <- inferKnownBackend @t @(m :+ ds)+ , Dict <- inferKnownBackend @t @((n + m) :+ ds)+ = unsafeAppendPB+ | otherwise = error "Numeri.DataFrame.Type/appendDF: impossible arguments"++-- | Append a small DataFrame to a big DataFrame on the left.+--+-- If you want to deconstruct a DataFrame, use+-- `Numeric.DataFrame.SubSpace.index`+-- or `Numeric.DataFrame.SubSpace.slice` instead.+consDF :: forall (n :: Nat) (ds :: [Nat]) (t :: Type)+ . ( PrimBytes t, Dimensions ds, KnownDim n )+ => DataFrame t ds+ -> DataFrame t (n :+ ds)+ -> DataFrame t ((n + 1) :+ ds)+consDF+ | D <- D @n `plusDim` D1+ , Dict <- inferKnownBackend @t @(n :+ ds)+ , Dict <- inferKnownBackend @t @ds+ , Dict <- inferKnownBackend @t @((n + 1) :+ ds)+ = unsafeAppendPB+ | otherwise = error "Numeri.DataFrame.Type/consDF: impossible arguments"++-- | Append a small DataFrame to a big DataFrame on the right.+--+-- If you want to deconstruct a DataFrame, use+-- `Numeric.DataFrame.SubSpace.index`+-- or `Numeric.DataFrame.SubSpace.slice` instead.+snocDF :: forall (n :: Nat) (ds :: [Nat]) (t :: Type)+ . ( PrimBytes t, Dimensions ds, KnownDim n )+ => DataFrame t (n :+ ds)+ -> DataFrame t ds+ -> DataFrame t ((n + 1) :+ ds)+snocDF+ | D <- D @n `plusDim` D1+ , Dict <- inferKnownBackend @t @(n :+ ds)+ , Dict <- inferKnownBackend @t @ds+ , Dict <- inferKnownBackend @t @((n + 1) :+ ds)+ = unsafeAppendPB+ | otherwise = error "Numeri.DataFrame.Type/snocDF: impossible arguments"+++-- | Unsafely copy two PrimBytes values into a third one.+unsafeAppendPB :: (PrimBytes x, PrimBytes y, PrimBytes z)+ => x -> y -> z+unsafeAppendPB x y+ | sx <- byteSize x+ = case runRW#+ ( \s0 -> case newByteArray# (sx +# byteSize y) s0 of+ (# s1, mba #) -> unsafeFreezeByteArray# mba+ ( writeBytes mba sx y+ ( writeBytes mba 0# x s1))+ ) of (# _, r #) -> fromBytes 0# r+++-- | Construct a DataFrame from a list of smaller DataFrames.+--+--+-- If the argument list is shorter than @d@, then the rest of the frame+-- is padded with a default value (first argument).+--+-- If the argument list is longer than @d@, then unused values are dropped.+-- If you want, you can pass an infinite list as an argument.+fromListWithDefault :: forall (t :: Type) (d :: Nat) (ds :: [Nat])+ . (PrimBytes t, Dimensions (d ': ds))+ => DataFrame t ds -> [DataFrame t ds] -> DataFrame t (d ': ds)+fromListWithDefault d ds = snd $ packDF' f ((,) ds)+ where+ f :: forall r . ([DataFrame t ds], DataFrame t ds -> r) -> ([DataFrame t ds], r)+ f ([] , k) = ([], k d)+ f (x:xs, k) = (xs, k x)++-- | Construct a dynamic DataFrame from a list of smaller DataFrames.+-- Pattern-match against the resulting @XFrame@ to find out its dimensionality.+--+-- You must not provide an infinite list as an argument.+fromList :: forall (t :: Type) (ds :: [Nat])+ . (PrimBytes t, Dimensions ds)+ => [DataFrame t ds] -> DataFrame t (XN 0 ': AsXDims ds)+fromList xs+ | Dx (D :: Dim n) <- someDimVal . fromIntegral $ length xs+ , Dict <- inferKnownBackend @t @(n ': ds)+ , ds@(AsXDims (XDims ds')) <- dims @ds+ , Just Dict <- sameDims ds ds'+ = XFrame (fromListWithDefault @t @n @ds undefined xs)+ | otherwise+ = error "Numeri.DataFrame.Type/fromList: impossible arguments"+++-- | Try to convert between @XNat@-indexed DataFrames.+--+-- This is useful for imposing restrictions on unknown DataFrames,+-- e.g. increasing the minimum number of elements.+constrainDF :: forall (ds :: [XNat]) (ys :: [XNat]) (l :: Type) (ts :: l)+ . (BoundedDims ds, All KnownXNatType ds)+ => DataFrame ts ys -> Maybe (DataFrame ts ds)+constrainDF (XFrame (df :: DataFrame ts ns))+ | ns <- dims @ns+ = case constrainDims @XNat @ds ns of+ Just (XDims (Dims :: Dims ms))+ | Dict <- unsafeEqTypes @[Nat] @ns @ms+ -> Just $ XFrame df+ _ -> Nothing++++-- Need this for @packDF'@ to make @Int -> c z@ a proper second-order type+-- parameterized by the result type.+newtype Off c z = Off { runOff :: Int -> c z }++-- | Term-level structure of a @SingleFrame t ds@ is fully determined by its+-- type dimensionality @Typeable ds@.+-- Thus, @gunfold@ does not use its last argument (@Constr@) at all,+-- relying on the structure of the type parameter.+instance (Data t, PrimBytes t, Typeable ds)+ => Data (DataFrame (t :: Type) (ds :: [Nat])) where+ gfoldl k z v = case typeableDims @ds of+ U | S x <- v+ -> z S `k` x+ D :* (Dims :: Dims ns)+ -> case inferTypeableCons @_ @ds of+ Dict ->+ -- PLZ don't ask me how does this work+ unpackDF' (\_ f -> runOff $ packDF'+ (\g -> Off . f $ k . runOff g)+ (Off . const . z)+ ) v+ gunfold k z _ = case typeableDims @ds of+ U -> k (z S)+ D :* (Dims :: Dims ns)+ -> case inferTypeableCons @_ @ds of Dict -> packDF' k z+ toConstr _ = case typeableDims @ds of+ U -> scalarFrameConstr+ d :* _ -> singleFrameConstr $ dimVal d+ dataTypeOf _ = case typeableDims @ds of+ U -> dataFrameDataType [scalarFrameConstr]+ d :* _ -> dataFrameDataType . (:[]). singleFrameConstr $ dimVal d++-- | Term-level structure of a @MultiFrame ts@ is fully determined by its+-- type @Typeable ts@.+-- Thus, @gunfold@ does not use its last argument (@Constr@) at all,+-- relying on the structure of the type parameter.+instance (AllFrames Data ts ds, Typeable ts, Typeable ds)+ => Data (DataFrame (ts :: [Type]) (ds :: [Nat])) where+ gfoldl _ z Z = z Z+ gfoldl k z (x :*: xs) = case inferTypeableCons @Type @ts of+ Dict -> z (:*:) `k` x `k` xs+ gunfold k z _ = case typeables @Type @ts of+ U -> z Z+ _ :* _ -> case inferTypeableCons @_ @ts of Dict -> k (k (z (:*:)))+ toConstr Z = multiFrameZConstr+ toConstr (_ :*: _) = multiFrameConsConstr+ dataTypeOf _ = dataFrameDataType [multiFrameZConstr, multiFrameConsConstr]+++dataFrameDataType :: [Constr] -> DataType+dataFrameDataType = mkDataType "Numeric.DataFrame.Type.DataFrame"++scalarFrameConstr :: Constr+scalarFrameConstr+ = mkConstr (dataFrameDataType [scalarFrameConstr]) "S" [] Prefix++singleFrameConstr :: Word -> Constr+singleFrameConstr d+ = mkConstr (dataFrameDataType [singleFrameConstr d]) ("DF" ++ show d) [] Prefix++multiFrameZConstr :: Constr+multiFrameZConstr = mkConstr+ (dataFrameDataType [multiFrameZConstr, multiFrameConsConstr])+ "Z" [] Prefix++multiFrameConsConstr :: Constr+multiFrameConsConstr = mkConstr+ (dataFrameDataType [multiFrameZConstr, multiFrameConsConstr])+ ":*:" [] Infix+++type DFMetaSel = 'G.MetaSel+ 'Nothing 'G.NoSourceUnpackedness 'G.NoSourceStrictness 'G.DecidedLazy++type family DFTree (t :: Type) (ds :: [Nat]) (d :: Nat) where+ DFTree t ds 0 = G.U1+ DFTree t ds 1 = G.S1 DFMetaSel (G.Rec0 (DataFrame t ds))+ DFTree t ds n = DFTree t ds (Div n 2) G.:*: DFTree t ds (Div n 2 + Mod n 2)++type family SingleFrameRep (t :: Type) (ds :: [Nat]) :: (Type -> Type) where+ SingleFrameRep t '[]+ = G.C1 ('G.MetaCons "S" 'G.PrefixI 'False) (G.S1 DFMetaSel (G.Rec0 t))+ SingleFrameRep t (d ': ds)+ = G.C1 ('G.MetaCons (AppendSymbol "DF" (ShowNat d)) 'G.PrefixI 'False) (DFTree t ds d)++instance (PrimBytes t, Dimensions ds)+ => G.Generic (DataFrame (t :: Type) (ds :: [Nat])) where+ type Rep (DataFrame t ds) = G.D1+ ('G.MetaData "DataFrame" "Numeric.DataFrame.Type" "easytensor" 'False)+ ( SingleFrameRep t ds )+ from = G.M1 . fromSingleFrame (dims @ds)+ to (G.M1 rep) = toSingleFrame (dims @ds) rep++fromSingleFrame :: forall (t :: Type) (ds :: [Nat]) (x :: Type)+ . PrimBytes t+ => Dims ds+ -> DataFrame t ds+ -> SingleFrameRep t ds x+fromSingleFrame U (S x) = G.M1 . G.M1 $ G.K1 x+fromSingleFrame (dd@D :* (Dims :: Dims ds')) x+ | Dict <- inferKnownBackend @t @ds+ , Dict <- inferKnownBackend @t @ds'+ = G.M1 $ case arrayContent# x of+ (# e | #) -> fillRep @_ @ds' (const $ broadcast e) 0 dd+ (# | (# cdims, off, arr #) #)+ | cd <- CumulDims . tail $ unCumulDims cdims+ , td <- cdTotalDim# cd+ -> fillRep @_ @ds'+ (\(W# i) -> fromElems cd (off +# td *# word2Int# i) arr) 0 dd+ where+ fillRep :: forall (n :: Nat) (ns :: [Nat])+ . (Word -> DataFrame t ns)+ -> Word+ -> Dim n+ -> DFTree t ns n x+ fillRep _ _ D0 = G.U1+ fillRep f i D1 = G.M1 . G.K1 $ f i+ fillRep f i d+ | Dict <- unsafeEqTypes @(Type -> Type)+ @(DFTree t ns n)+ @(DFTree t ns (Div n 2) G.:*: DFTree t ns (Div n 2 + Mod n 2))+ = fillRep f i d2 G.:*: fillRep f (i + dimVal d2) d2'+ where+ d2 = divDim d D2+ d2' = d2 `plusDim` modDim d D2++toSingleFrame :: forall (t :: Type) (ds :: [Nat]) (x :: Type)+ . PrimBytes t+ => Dims ds+ -> SingleFrameRep t ds x+ -> DataFrame t ds+toSingleFrame U (G.M1 (G.M1 (G.K1 x))) = S x+toSingleFrame (dd@D :* (Dims :: Dims ds')) (G.M1 rep)+ | Dict <- inferKnownBackend @t @ds+ , Dict <- inferKnownBackend @t @ds'+ , els <- case dimVal dd of W# w -> word2Int# w+ , asize <- byteSize @(DataFrame t ds') undefined+ = runRW#+ ( \s0 -> case newByteArray# (asize *# els) s0 of+ (# s1, mba #)+ | s2 <- fillDF @_ @ds'+ (\(W# i) df -> writeBytes mba (asize *# word2Int# i) df)+ 0 dd rep s1+ , (# _, ba #) <- unsafeFreezeByteArray# mba s2+ -> fromBytes 0# ba+ )+ where+ fillDF :: forall (n :: Nat) (ns :: [Nat]) s+ . (Word -> DataFrame t ns -> State# s -> State# s)+ -> Word+ -> Dim n+ -> DFTree t ns n x+ -> State# s -> State# s+ fillDF _ _ D0 _ s = s+ fillDF f i D1 (G.M1 (G.K1 e)) s = f i e s+ fillDF f i d xy s+ | Dict <- unsafeEqTypes @(Type -> Type)+ @(DFTree t ns n)+ @(DFTree t ns (Div n 2) G.:*: DFTree t ns (Div n 2 + Mod n 2))+ , x G.:*: y <- xy+ = fillDF f (i + dimVal d2) d2' y (fillDF f i d2 x s)+ where+ d2 = divDim d D2+ d2' = d2 `plusDim` modDim d D2+++type family MultiFrameRepNil (ts :: [Type]) :: (Type -> Type) where+ MultiFrameRepNil '[] = G.C1 ('G.MetaCons "Z" 'G.PrefixI 'False) G.U1+ MultiFrameRepNil (_ ': _) = G.Rec0 Void++type family MultiFrameRepCons (ts :: [Type]) (ds :: [Nat]) :: (Type -> Type) where+ MultiFrameRepCons '[] _ = G.Rec0 Void+ MultiFrameRepCons (t ': ts) ds = G.C1+ ('G.MetaCons ":*:" ('G.InfixI 'G.RightAssociative 6) 'False)+ ( G.S1 DFMetaSel+ (G.Rec0 (DataFrame t ds))+ G.:*:+ G.S1 DFMetaSel+ (G.Rec0 (DataFrame ts ds))+ )++instance G.Generic (DataFrame (ts :: [Type]) (ds :: [Nat])) where+ type Rep (DataFrame ts ds) = G.D1+ ('G.MetaData "DataFrame" "Numeric.DataFrame.Type" "easytensor" 'False)+ ( MultiFrameRepNil ts G.:+: MultiFrameRepCons ts ds )+ from Z = G.M1 (G.L1 (G.M1 G.U1))+ from (x :*: xs) = G.M1 (G.R1 (G.M1 (G.M1 (G.K1 x) G.:*: G.M1 (G.K1 xs))))+ to (G.M1 (G.L1 _))+ | Dict <- unsafeEqTypes @[Type] @ts @'[] = Z+ to (G.M1 (G.R1 xxs))+ | Dict <- unsafeEqTypes @[Type] @ts @(Head ts ': Tail ts)+ , G.M1 (G.M1 (G.K1 x) G.:*: G.M1 (G.K1 xs)) <- xxs = x :*: xs++++unsafeEqTypes :: forall k (a :: k) (b :: k) . Dict (a ~ b)+unsafeEqTypes = unsafeCoerce# (Dict :: Dict (a ~ a))
src/Numeric/Matrix.hs view
@@ -1,32 +1,3 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UnboxedSums #-}-{-# LANGUAGE UnboxedTuples #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--------------------------------------------------------------------------------- |--- Module : Numeric.Matrix--- Copyright : (c) Artem Chirkin--- License : BSD3------ Maintainer : chirkin@arch.ethz.ch------------------------------------------------------------------------------------- module Numeric.Matrix ( MatrixTranspose (..) , SquareMatrix (..)@@ -46,300 +17,7 @@ , pivotMat, luSolve ) where --import Control.Monad (foldM)-import Data.Foldable (forM_, foldl')-import Data.List (delete)-import GHC.Base-import Numeric.DataFrame.Contraction ((%*))-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.Family as AFam-import Numeric.DataFrame.Shape-import Numeric.DataFrame.SubSpace-import Numeric.DataFrame.Type-import Numeric.Dimensions-import Numeric.Matrix.Class-import Numeric.Matrix.Mat44d ()-import Numeric.Matrix.Mat44f ()-import Numeric.PrimBytes-import Numeric.Scalar-import Numeric.Vector--import Control.Monad.ST-import Numeric.DataFrame.ST------ | Compose a 2x2D matrix-mat22 :: ( PrimBytes (Vector (t :: Type) 2)- , PrimBytes (Matrix t 2 2)- )- => Vector t 2 -> Vector t 2 -> Matrix t 2 2-mat22 = (<::>)---- | Compose a 3x3D matrix-mat33 :: ( PrimBytes (t :: Type)- , PrimBytes (Vector t 3)- , PrimBytes (Matrix t 3 3)- )- => Vector t 3 -> Vector t 3 -> Vector t 3 -> Matrix t 3 3-mat33 a b c = runST $ do- mmat <- newDataFrame- copyDataFrame a (1:*1:*U) mmat- copyDataFrame b (1:*2:*U) mmat- copyDataFrame c (1:*3:*U) mmat- unsafeFreezeDataFrame mmat---- | Compose a 4x4D matrix-mat44 :: forall (t :: Type)- . ( PrimBytes t- , PrimBytes (Vector t (4 :: Nat))- , PrimBytes (Matrix t (4 :: Nat) (4 :: Nat))- )- => Vector t (4 :: Nat)- -> Vector t (4 :: Nat)- -> Vector t (4 :: Nat)- -> Vector t (4 :: Nat)- -> Matrix t (4 :: Nat) (4 :: Nat)-mat44 a b c d = runST $ do- mmat <- newDataFrame- copyDataFrame a (1:*1:*U) mmat- copyDataFrame b (1:*2:*U) mmat- copyDataFrame c (1:*3:*U) mmat- copyDataFrame d (1:*4:*U) mmat- unsafeFreezeDataFrame mmat----instance ( KnownDim n, KnownDim m- , PrimArray t (Matrix t n m)- , PrimArray t (Matrix t m n)- ) => MatrixTranspose t (n :: Nat) (m :: Nat) where- transpose df = case elemSize0 df of- 0# -> broadcast (ix# 0# df)- nm | I# m <- fromIntegral $ dimVal' @m- , I# n <- fromIntegral $ dimVal' @n- -> let f ( I# j, I# i )- | isTrue# (j ==# m) = f ( 0 , I# (i +# 1#) )- | otherwise = (# ( I# (j +# 1#), I# i )- , ix# (j *# n +# i) df- #)- in case gen# nm f (0,0) of- (# _, r #) -> r--instance MatrixTranspose (t :: Type) (xn :: XNat) (xm :: XNat) where- transpose (XFrame (df :: DataFrame t ns))- | ((D :: Dim n) :* (D :: Dim m) :* U) <- dims @Nat @ns- , E <- AFam.inferPrimElem @t @n @'[m]- = XFrame (transpose df :: Matrix t m n)- transpose _ = error "MatrixTranspose/transpose: impossible argument"--instance (KnownDim n, PrimArray t (Matrix t n n), Num t)- => SquareMatrix t n where- eye- | n@(I# n#) <- fromIntegral $ dimVal' @n- = let f 0 = (# n, 1 #)- f k = (# k - 1, 0 #)- in case gen# (n# *# n#) f 0 of- (# _, r #) -> r- diag se- | n@(I# n#) <- fromIntegral $ dimVal' @n- , e <- unScalar se- = let f 0 = (# n, e #)- f k = (# k - 1, 0 #)- in case gen# (n# *# n#) f 0 of- (# _, r #) -> r- trace df- | I# n <- fromIntegral $ dimVal' @n- , n1 <- n +# 1#- = let f 0# = ix# 0# df- f k = ix# k df + f (k -# n1)- in scalar $ f (n *# n -# 1#)---instance ( KnownDim n, Ord t, Fractional t- , PrimBytes t- , PrimArray t (Matrix t n n)- , PrimArray t (Vector t n)- , PrimBytes (Vector t n)- , PrimBytes (Matrix t n n)- )- => MatrixInverse t n where- inverse m = ewmap (luSolve (lu m)) eye---instance ( KnownDim n, Ord t, Fractional t- , PrimBytes t, PrimArray t (Matrix t n n))- => MatrixDeterminant t n where- det m = prodF (luUpper f) * prodF (luLower f) * luPermSign f- where- f = lu m- !(I# n) = fromIntegral $ dimVal' @n- n1 = n +# 1#- nn1 = n *# n -# 1#- prodF a = scalar $ prodF' nn1 a- prodF' 0# a = ix# 0# a- prodF' k a = ix# k a * prodF' (k -# n1) a---instance ( KnownDim n, Ord t, Fractional t- , PrimBytes t, PrimArray t (Matrix t n n))- => MatrixLU t n where- lu m' = case runRW# go of- (# _, (# bu, bl #) #) -> LUFact- { luLower = fromElems 0# nn bl- , luUpper = fromElems 0# nn bu- , luPerm = p- , luPermSign = si- }- where- (m, p, si) = pivotMat m'- !(I# n) = fromIntegral $ dimVal' @n- nn = n *# n- tbs = byteSize @t undefined- bsize = nn *# tbs- ixm i j = ix# (i +# n *# j) m- loop :: (Int# -> a -> State# s -> (# State# s, a #))- -> Int# -> Int# -> a -> State# s -> (# State# s, a #)- loop f i k x s- | isTrue# (i ==# k) = (# s, x #)- | otherwise = case f i x s of- (# s', y #) -> loop f ( i +# 1# ) k y s'- go s0- | (# s1, mbl #) <- newByteArray# bsize s0- , (# s2, mbu #) <- newByteArray# bsize s1- , s3 <- setByteArray# mbl 0# bsize 0# s2- , s4 <- setByteArray# mbu 0# bsize 0# s3- , readL <- \i j -> readArray @t mbl (i +# n *# j)- , readU <- \i j -> readArray @t mbu (i +# n *# j)- , writeL <- \i j -> writeArray @t mbl (i +# n *# j)- , writeU <- \i j -> writeArray @t mbu (i +# n *# j)- , computeU <- \i j ->- let f k x s- | (# s' , ukj #) <- readU k j s- , (# s'', lik #) <- readL i k s'- = (# s'', x - ukj * lik #)- in loop f 0# i (ixm i j)- , computeL' <- \i j ->- let f k x s- | (# s' , ukj #) <- readU k j s- , (# s'', lik #) <- readL i k s'- = (# s'', x - ukj * lik #)- in loop f 0# j (ixm i j)- , (# sr, () #) <-- loop- ( \j _ sj -> case sj of- sj0- | sj1 <- writeL j j 1 sj0- , (# sj2, () #) <- loop- ( \i _ sij0 -> case computeU i j sij0 of- (# sij1, uij #) -> (# writeU i j uij sij1, () #)- ) 0# j () sj1- , (# sj3, ujj #) <- computeU j j sj2- , sj4 <- writeU j j ujj sj3- -> case ujj of- 0 -> loop- ( \i _ sij -> (# writeL i j 0 sij, () #)- ) (j +# 1#) n () sj4- x -> loop- ( \i _ sij0 -> case computeL' i j sij0 of- (# sij1, lij #) -> (# writeL i j (lij / x) sij1, () #)- ) (j +# 1#) n () sj4- ) 0# n () s4- , (# sf0, bl #) <- unsafeFreezeByteArray# mbl sr- , (# sf1, bu #) <- unsafeFreezeByteArray# mbu sf0- = (# sf1, (# bu, bl #) #)----- | Solve @Ax = b@ problem given LU decomposition of A.-luSolve :: forall (t :: Type) (n :: Nat)- . ( KnownDim n, Ord t, Fractional t- , PrimBytes t, PrimArray t (Matrix t n n), PrimArray t (Vector t n))- => LUFact t n -> Vector t n -> Vector t n-luSolve LUFact {..} b = x- where- -- Pb = LUx- pb = luPerm %* b- !n@(I# n#) = fromIntegral $ dimVal' @n- -- Ly = Pb- y :: Vector t n- y = runST $ do- my <- newDataFrame- let ixA (I# i) (I# j) = scalar $ ix# (i +# n# *# j) luLower- ixB (I# i) = scalar $ ix# i pb- forM_ [0..n-1] $ \i -> do- v <- foldM ( \v j -> do- dj <- readDataFrameOff my j- return $ v - dj * ixA i j- ) (ixB i) [0..i-1]- writeDataFrameOff my i v- unsafeFreezeDataFrame my- -- Ux = y- x = runST $ do- mx <- newDataFrame- let ixA (I# i) (I# j) = scalar $ ix# (i +# n# *# j) luUpper- ixB (I# i) = scalar $ ix# i y- forM_ [n-1, n-2 .. 0] $ \i -> do- v <- foldM ( \v j -> do- dj <- readDataFrameOff mx j- return $ v - dj * ixA i j- ) (ixB i) [i+1..n-1]- writeDataFrameOff mx i (v / ixA i i)- unsafeFreezeDataFrame mx----- | Permute rows that the largest magnitude elements in columns are on diagonals.------ Invariants of result matrix:--- * forall j >= i: |M[i,i]| >= M[j,i]--- * if M[i,i] == 0 then forall j >= i: |M[i+1,i+1]| >= M[j,i+1]-pivotMat :: forall (t :: Type) (n :: k)- . (KnownDim n, PrimArray t (Matrix t n n), Ord t, Num t)- => Matrix t n n -> ( Matrix t n n -- permutated matrix- , Matrix t n n -- permutation matrix- , Scalar t -- sign of permutation matrix- )-pivotMat m- = ( let f ( j, [] ) = f (j+1, rowOrder)- f ( j, i:is ) = (# (j, is), ix i j #)- in case gen# nn f (0,rowOrder) of- (# _, r #) -> r- , let f ( j, [] ) = f (j+1, rowOrder)- f ( j, x:xs )- | j == x = (# ( j, xs), 1 #)- | otherwise = (# ( j, xs), 0 #)- in case gen# nn f (0,rowOrder) of- (# _, r #) -> r- , if countMisordered rowOrder `rem` 2 == 1- then -1 else 1- )- where- -- permuted row ordering- rowOrder = uncurry fillPass $ searchPass 0 [0..n-1]- -- matrix size- !n@(I# n#) = fromIntegral $ dimVal' @n- -- sign of permutations- countMisordered :: [Int] -> Int- countMisordered [] = 0- countMisordered (i:is) = foldl' (\c j -> if i > j then succ c else c) 0 is- + countMisordered is- nn = n# *# n#- ix (I# i) (I# j) = ix# (i +# j *# n#) m- findMax :: Int -> [Int] -> (t, Int)- findMax j = foldl' (\(ox, oi) i -> let x = abs (ix i j)- in if x > ox then (x, i)- else (ox, oi)- ) (0, 0)- -- search maximums, leaving Nothing where all rows are 0- searchPass :: Int -> [Int] -> ([Int], [Maybe Int])- searchPass j is- | j == n = (is, [])- | otherwise = case findMax j is of- (0, _) -> (Nothing:) <$> searchPass (j+1) is- (_, i) -> (Just i:) <$> searchPass (j+1) (delete i is)- -- replace Nothings with remaining row numbers- fillPass :: [Int] -> [Maybe Int] -> [Int]- fillPass _ [] = []- fillPass js (Just i : is) = i : fillPass js is- fillPass (j:js) (Nothing : is) = j : fillPass js is- fillPass [] (Nothing : is) = 0 : fillPass [] is+import Numeric.DataFrame.Internal.Backend ()+import Numeric.Matrix.Internal+import Numeric.Matrix.Internal.Mat44d ()+import Numeric.Matrix.Internal.Mat44f ()
− src/Numeric/Matrix/Class.hs
@@ -1,151 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}-module Numeric.Matrix.Class- ( MatrixTranspose (..)- , SquareMatrix (..)- , MatrixDeterminant (..)- , MatrixInverse (..)- , MatrixLU (..), LUFact (..)- , Matrix- , HomTransform4 (..)- , Mat22f, Mat23f, Mat24f- , Mat32f, Mat33f, Mat34f- , Mat42f, Mat43f, Mat44f- , Mat22d, Mat23d, Mat24d- , Mat32d, Mat33d, Mat34d- , Mat42d, Mat43d, Mat44d- ) where--import Numeric.DataFrame.Family-import Numeric.Dimensions (Nat)-import Numeric.Scalar-import Numeric.Vector---- | Alias for DataFrames of rank 2-type Matrix (t :: l) (n :: k) (m :: k) = DataFrame t '[n,m]--class MatrixTranspose t (n :: k) (m :: k) where- -- | Transpose Mat- transpose :: Matrix t n m -> Matrix t m n- -- (MatrixTranspose t m n, PrimBytes (Matrix t m n)) =>--class SquareMatrix t (n :: Nat) where- -- | Mat with 1 on diagonal and 0 elsewhere- eye :: Matrix t n n- -- | Put the same value on the Mat diagonal, 0 otherwise- diag :: Scalar t -> Matrix t n n- -- | Sum of diagonal elements- trace :: Matrix t n n -> Scalar t--class MatrixDeterminant t (n :: Nat) where- -- | Determinant of Mat- det :: Matrix t n n -> Scalar t--class MatrixInverse t (n :: Nat) where- -- | Matrix inverse- inverse :: Matrix t n n -> Matrix t n n----- | Result of LU factorization with Partial Pivoting--- @ PA = LU @.-data LUFact t n- = LUFact- { luLower :: Matrix t n n- -- ^ Lower triangular matrix @L@.- -- All elements on the diagonal of @L@ equal @1@.- , luUpper :: Matrix t n n- -- ^ Upper triangular matrix @U@- , luPerm :: Matrix t n n- -- ^ Row permutation matrix @P@- , luPermSign :: Scalar t- -- ^ Sign of permutation @luPermSign == det . luPerm@- }--deriving instance (Show (Matrix t n n), Show t) => Show (LUFact t n)-deriving instance (Eq (Matrix t n n), Eq t) => Eq (LUFact t n)--class MatrixLU t (n :: Nat) where- -- | Compute LU factorization with Partial Pivoting- lu :: Matrix t n n -> LUFact t n----- | Operations on 4x4 transformation matrices and vectors in homogeneous coordinates.--- All angles are specified in radians.-class HomTransform4 t where- -- | Create a translation matrix from a vector. The 4th coordinate is ignored.- translate4 :: Vector t 4 -> Matrix t 4 4- -- | Create a translation matrix from a vector.- translate3 :: Vector t 3 -> Matrix t 4 4- -- | Rotation matrix for a rotation around the X axis, angle is given in radians.- rotateX :: t -> Matrix t 4 4- -- | Rotation matrix for a rotation around the Y axis, angle is given in radians.- rotateY :: t -> Matrix t 4 4- -- | Rotation matrix for a rotation around the Z axis, angle is given in radians.- rotateZ :: t -> Matrix t 4 4- -- | Rotation matrix for a rotation around an arbitrary normalized vector- rotate :: Vector t 3 -> t -> Matrix t 4 4- -- | Rotation matrix from the Euler angles roll (axis @Z@), yaw (axis @Y'@), and pitch (axis @X''@).- -- This order is known as Tait-Bryan angles (@Z-Y'-X''@ intrinsic rotations), or nautical angles, or Cardan angles.- -- - -- > rotateEuler pitch yaw roll == rotateX pitch %* rotateY yaw %* rotateZ roll- --- -- https://en.wikipedia.org/wiki/Euler_angles#Conventions_2- rotateEuler :: t -- ^ pitch (axis @X''@)- -> t -- ^ yaw (axis @Y'@)- -> t -- ^ roll (axis @Z@)- -> Matrix t 4 4- -- | Create a transform matrix using up direction, camera position and a point to look at.- -- Just the same as GluLookAt.- lookAt :: Vector t 3 -- ^ The up direction, not necessary unit length or perpendicular to the view vector- -> Vector t 3 -- ^ The viewers position- -> Vector t 3 -- ^ The point to look at- -> Matrix t 4 4- -- | A perspective symmetric projection matrix. Right-handed coordinate system. (@x@ - right, @y@ - top)- -- http://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations- perspective :: t -- ^ Near plane clipping distance (always positive)- -> t -- ^ Far plane clipping distance (always positive)- -> t -- ^ Field of view of the y axis, in radians- -> t -- ^ Aspect ratio, i.e. screen's width\/height- -> Matrix t 4 4- -- | An orthogonal symmetric projection matrix. Right-handed coordinate system. (@x@ - right, @y@ - top)- -- http://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations- orthogonal :: t -- ^ Near plane clipping distance- -> t -- ^ Far plane clipping distance- -> t -- ^ width- -> t -- ^ height- -> Matrix t 4 4- -- | Add one more dimension and set it to 1.- toHomPoint :: Vector t 3 -> Vector t 4- -- | Add one more dimension and set it to 0.- toHomVector :: Vector t 3 -> Vector t 4- -- | Transform a homogenous vector or point into a normal 3D vector.- -- If the last coordinate is not zero, divide the rest by it.- fromHom :: Vector t 4 -> Vector t 3---- Type abbreviations--type Mat22f = Matrix Float 2 2-type Mat32f = Matrix Float 3 2-type Mat42f = Matrix Float 4 2-type Mat23f = Matrix Float 2 3-type Mat33f = Matrix Float 3 3-type Mat43f = Matrix Float 4 3-type Mat24f = Matrix Float 2 4-type Mat34f = Matrix Float 3 4-type Mat44f = Matrix Float 4 4--type Mat22d = Matrix Double 2 2-type Mat32d = Matrix Double 3 2-type Mat42d = Matrix Double 4 2-type Mat23d = Matrix Double 2 3-type Mat33d = Matrix Double 3 3-type Mat43d = Matrix Double 4 3-type Mat24d = Matrix Double 2 4-type Mat34d = Matrix Double 3 4-type Mat44d = Matrix Double 4 4
+ src/Numeric/Matrix/Internal.hs view
@@ -0,0 +1,473 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.Matrix.Internal+ ( MatrixTranspose (..)+ , SquareMatrix (..)+ , MatrixDeterminant (..)+ , MatrixInverse (..)+ , MatrixLU (..), LUFact (..)+ , Matrix+ , HomTransform4 (..)+ , Mat22f, Mat23f, Mat24f+ , Mat32f, Mat33f, Mat34f+ , Mat42f, Mat43f, Mat44f+ , Mat22d, Mat23d, Mat24d+ , Mat32d, Mat33d, Mat34d+ , Mat42d, Mat43d, Mat44d+ , mat22, mat33, mat44+ , (%*)+ , pivotMat, luSolve+ ) where++import Control.Monad (foldM)+import Control.Monad.ST+import Data.Foldable (foldl', forM_)+import Data.List (delete)+import GHC.Base+import Numeric.DataFrame.Contraction ((%*))+import Numeric.DataFrame.Internal.PrimArray+import Numeric.DataFrame.ST+import Numeric.DataFrame.SubSpace+import Numeric.DataFrame.Type+import Numeric.Dimensions+import Numeric.PrimBytes+import Numeric.Scalar.Internal+import Numeric.Vector.Internal++-- | Alias for DataFrames of rank 2+type Matrix (t :: l) (n :: k) (m :: k) = DataFrame t '[n,m]++class MatrixTranspose t (n :: k) (m :: k) where+ -- | Transpose Mat+ transpose :: Matrix t n m -> Matrix t m n++class SquareMatrix t (n :: Nat) where+ -- | Mat with 1 on diagonal and 0 elsewhere+ eye :: Matrix t n n+ -- | Put the same value on the Mat diagonal, 0 otherwise+ diag :: Scalar t -> Matrix t n n+ -- | Sum of diagonal elements+ trace :: Matrix t n n -> Scalar t++class MatrixDeterminant t (n :: Nat) where+ -- | Determinant of Mat+ det :: Matrix t n n -> Scalar t++class MatrixInverse t (n :: Nat) where+ -- | Matrix inverse+ inverse :: Matrix t n n -> Matrix t n n+++-- | Result of LU factorization with Partial Pivoting+-- @ PA = LU @.+data LUFact t n+ = LUFact+ { luLower :: Matrix t n n+ -- ^ Lower triangular matrix @L@.+ -- All elements on the diagonal of @L@ equal @1@.+ , luUpper :: Matrix t n n+ -- ^ Upper triangular matrix @U@+ , luPerm :: Matrix t n n+ -- ^ Row permutation matrix @P@+ , luPermSign :: Scalar t+ -- ^ Sign of permutation @luPermSign == det . luPerm@+ }++deriving instance (Show t, PrimBytes t, KnownDim n) => Show (LUFact t n)+deriving instance (Eq (Matrix t n n), Eq t) => Eq (LUFact t n)++class MatrixLU t (n :: Nat) where+ -- | Compute LU factorization with Partial Pivoting+ lu :: Matrix t n n -> LUFact t n+++-- | Operations on 4x4 transformation matrices and vectors in homogeneous coordinates.+-- All angles are specified in radians.+--+-- Note: since version 2 of @easytensor@, DataFrames and matrices are row-major.+-- A good SIMD implementation may drastically improve performance+-- of 4D vector-matrix products of the form @v %* m@, but not so much+-- for products of the form @m %* v@ (due to memory layout).+-- Thus, all operations here assume the former form to benefit more from+-- SIMD in future.+class HomTransform4 t where+ -- | Create a translation matrix from a vector. The 4th coordinate is ignored.+ --+ -- If @p ! 3 == 1@ and @v ! 3 == 0@, then+ --+ -- > p %* translate4 v == p + v+ --+ translate4 :: Vector t 4 -> Matrix t 4 4+ -- | Create a translation matrix from a vector.+ --+ -- If @p ! 3 == 1@, then+ --+ -- > p %* translate3 v == p + toHomVector v+ --+ translate3 :: Vector t 3 -> Matrix t 4 4+ -- | Rotation matrix for a rotation around the X axis, angle is given in radians.+ -- e.g. @p %* rotateX (pi/2)@ rotates point @p@ around @Ox@ by 90 degrees.+ rotateX :: t -> Matrix t 4 4+ -- | Rotation matrix for a rotation around the Y axis, angle is given in radians.+ -- e.g. @p %* rotateY (pi/2)@ rotates point @p@ around @Oy@ by 90 degrees.+ rotateY :: t -> Matrix t 4 4+ -- | Rotation matrix for a rotation around the Z axis, angle is given in radians.+ -- e.g. @p %* rotateZ (pi/2)@ rotates point @p@ around @Oz@ by 90 degrees.+ rotateZ :: t -> Matrix t 4 4+ -- | Rotation matrix for a rotation around an arbitrary normalized vector+ -- e.g. @p %* rotate (pi/2) v@ rotates point @p@ around @v@ by 90 degrees.+ rotate :: Vector t 3 -> t -> Matrix t 4 4+ -- | Rotation matrix from the Euler angles roll (axis @Z@), yaw (axis @Y'@), and pitch (axis @X''@).+ -- This order is known as Tait-Bryan angles (@Z-Y'-X''@ intrinsic rotations), or nautical angles, or Cardan angles.+ --+ -- > rotateEuler pitch yaw roll == rotateZ roll %* rotateY yaw %* rotateX pitch+ --+ -- https://en.wikipedia.org/wiki/Euler_angles#Conventions_2+ rotateEuler :: t -- ^ pitch (axis @X''@)+ -> t -- ^ yaw (axis @Y'@)+ -> t -- ^ roll (axis @Z@)+ -> Matrix t 4 4+ -- | Create a transform matrix using up direction, camera position and a point to look at.+ -- Just the same as GluLookAt.+ lookAt :: Vector t 3 -- ^ The up direction, not necessary unit length or perpendicular to the view vector+ -> Vector t 3 -- ^ The viewers position+ -> Vector t 3 -- ^ The point to look at+ -> Matrix t 4 4+ -- | A perspective symmetric projection matrix. Right-handed coordinate system. (@x@ - right, @y@ - top)+ -- http://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations+ perspective :: t -- ^ Near plane clipping distance (always positive)+ -> t -- ^ Far plane clipping distance (always positive)+ -> t -- ^ Field of view of the y axis, in radians+ -> t -- ^ Aspect ratio, i.e. screen's width\/height+ -> Matrix t 4 4+ -- | An orthogonal symmetric projection matrix. Right-handed coordinate system. (@x@ - right, @y@ - top)+ -- http://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations+ orthogonal :: t -- ^ Near plane clipping distance+ -> t -- ^ Far plane clipping distance+ -> t -- ^ width+ -> t -- ^ height+ -> Matrix t 4 4+ -- | Add one more dimension and set it to 1.+ toHomPoint :: Vector t 3 -> Vector t 4+ -- | Add one more dimension and set it to 0.+ toHomVector :: Vector t 3 -> Vector t 4+ -- | Transform a homogenous vector or point into a normal 3D vector.+ -- If the last coordinate is not zero, divide the rest by it.+ fromHom :: Vector t 4 -> Vector t 3++-- Type abbreviations++type Mat22f = Matrix Float 2 2+type Mat32f = Matrix Float 3 2+type Mat42f = Matrix Float 4 2+type Mat23f = Matrix Float 2 3+type Mat33f = Matrix Float 3 3+type Mat43f = Matrix Float 4 3+type Mat24f = Matrix Float 2 4+type Mat34f = Matrix Float 3 4+type Mat44f = Matrix Float 4 4++type Mat22d = Matrix Double 2 2+type Mat32d = Matrix Double 3 2+type Mat42d = Matrix Double 4 2+type Mat23d = Matrix Double 2 3+type Mat33d = Matrix Double 3 3+type Mat43d = Matrix Double 4 3+type Mat24d = Matrix Double 2 4+type Mat34d = Matrix Double 3 4+type Mat44d = Matrix Double 4 4+++-- | Compose a 2x2D matrix+mat22 :: PrimBytes (t :: Type)+ => Vector t 2 -> Vector t 2 -> Matrix t 2 2+mat22 = packDF @_ @2 @'[2]+{-# INLINE mat22 #-}++-- | Compose a 3x3D matrix+mat33 :: PrimBytes (t :: Type)+ => Vector t 3 -> Vector t 3 -> Vector t 3 -> Matrix t 3 3+mat33 = packDF @_ @3 @'[3]+{-# INLINE mat33 #-}++-- | Compose a 4x4D matrix+mat44 :: PrimBytes (t :: Type)+ => Vector t 4+ -> Vector t 4+ -> Vector t 4+ -> Vector t 4+ -> Matrix t 4 4+mat44 = packDF @_ @4 @'[4]+{-# INLINE mat44 #-}++++instance ( KnownDim n, KnownDim m+ , PrimArray t (Matrix t n m)+ , PrimArray t (Matrix t m n)+ ) => MatrixTranspose t (n :: Nat) (m :: Nat) where+ transpose df = case uniqueOrCumulDims df of+ Left a -> broadcast a+ Right _+ | wm <- dimVal' @m+ , wn <- dimVal' @n+ , m <- case wm of W# w -> word2Int# w+ , n <- case wn of W# w -> word2Int# w+ -> let f ( I# i, I# j )+ | isTrue# (i ==# n) = f ( 0, I# (j +# 1#) )+ | otherwise = (# ( I# (i +# 1#), I# j )+ , ix# (i *# m +# j) df+ #)+ in case gen# (CumulDims [wm*wn, wn, 1]) f (0,0) of (# _, r #) -> r++instance MatrixTranspose (t :: Type) (xn :: XNat) (xm :: XNat) where+ transpose (XFrame (df :: DataFrame t ns))+ | ((D :: Dim n) :* (D :: Dim m) :* U) <- dims @ns+ , Dict <- inferPrimElem df+ = XFrame (transpose df :: Matrix t m n)+ transpose _ = error "MatrixTranspose/transpose: impossible argument"++instance (KnownDim n, PrimArray t (Matrix t n n), Num t)+ => SquareMatrix t n where+ eye+ | n <- dimVal' @n+ = let f 0 = (# n , 1 #)+ f k = (# k - 1, 0 #)+ in case gen# (CumulDims [n*n, n, 1]) f 0 of+ (# _, r #) -> r+ diag se+ | n <- dimVal' @n+ , e <- unScalar se+ = let f 0 = (# n , e #)+ f k = (# k - 1, 0 #)+ in case gen# (CumulDims [n*n, n, 1]) f 0 of+ (# _, r #) -> r+ trace df+ | I# n <- fromIntegral $ dimVal' @n+ , n1 <- n +# 1#+ = let f 0# = ix# 0# df+ f k = ix# k df + f (k -# n1)+ in scalar $ f (n *# n -# 1#)+++instance ( KnownDim n, Ord t, Fractional t+ , PrimBytes t+ , PrimArray t (Matrix t n n)+ , PrimArray t (Vector t n)+ , PrimBytes (Vector t n)+ , PrimBytes (Matrix t n n)+ )+ => MatrixInverse t n where+ inverse m = runST $ do+ m' <- newDataFrame+ indexWise_ @t @'[n] @'[n] @'[n, n] @_ @()+ (\is ->+ indexWise_ @t @'[n] @'[] @'[n] @_ @()+ (\(j:*U) -> writeDataFrame m' (j:*is)) . luSolve luM+ ) eye+ unsafeFreezeDataFrame m'+ where+ luM = lu m++ -- much nicer, but probably slower version:+ -- (it is not particularly fast to do an extra transpose+ -- before calculating the inverse)+ -- ewmap (luSolve . lu $ transpose m) eye++++instance ( KnownDim n, Ord t, Fractional t+ , PrimBytes t, PrimArray t (Matrix t n n))+ => MatrixDeterminant t n where+ det m = prodF (luUpper f) * prodF (luLower f) * luPermSign f+ where+ f = lu m+ n = case dimVal' @n of W# w -> word2Int# w+ n1 = n +# 1#+ nn1 = n *# n -# 1#+ prodF a = scalar $ prodF' nn1 a+ prodF' 0# a = ix# 0# a+ prodF' k a = ix# k a * prodF' (k -# n1) a+++instance ( KnownDim n, Ord t, Fractional t+ , PrimBytes t, PrimArray t (Matrix t n n))+ => MatrixLU t n where+ lu m' = case runRW# go of+ (# _, (# bu, bl #) #) -> LUFact+ { luLower = fromElems steps 0# bl+ , luUpper = fromElems steps 0# bu+ , luPerm = p+ , luPermSign = si+ }+ where+ dn = dimVal' @n+ dnn = dn * dn+ steps = CumulDims [dnn, dn, 1]+ (m, p, si) = pivotMat m'+ n = case dn of W# w -> word2Int# w+ nn = case dnn of W# w -> word2Int# w+ tbs = byteSize @t undefined+ bsize = nn *# tbs+ ixm i j = ix# (i *# n +# j) m+ loop :: (Int# -> a -> State# s -> (# State# s, a #))+ -> Int# -> Int# -> a -> State# s -> (# State# s, a #)+ loop f i k x s+ | isTrue# (i ==# k) = (# s, x #)+ | otherwise = case f i x s of+ (# s', y #) -> loop f ( i +# 1# ) k y s'+ go s0+ | (# s1, mbl #) <- newByteArray# bsize s0+ , (# s2, mbu #) <- newByteArray# bsize s1+ , s3 <- setByteArray# mbl 0# bsize 0# s2+ , s4 <- setByteArray# mbu 0# bsize 0# s3+ , readL <- \i j -> readArray @t mbl (i *# n +# j)+ , readU <- \i j -> readArray @t mbu (i *# n +# j)+ , writeL <- \i j -> writeArray @t mbl (i *# n +# j)+ , writeU <- \i j -> writeArray @t mbu (i *# n +# j)+ , computeU <- \i j ->+ let f k x s+ | (# s' , ukj #) <- readU k j s+ , (# s'', lik #) <- readL i k s'+ = (# s'', x - ukj * lik #)+ in loop f 0# i (ixm i j)+ , computeL' <- \i j ->+ let f k x s+ | (# s' , ukj #) <- readU k j s+ , (# s'', lik #) <- readL i k s'+ = (# s'', x - ukj * lik #)+ in loop f 0# j (ixm i j)+ , (# sr, () #) <-+ loop+ ( \j _ sj -> case sj of+ sj0+ | sj1 <- writeL j j 1 sj0+ , (# sj2, () #) <- loop+ ( \i _ sij0 -> case computeU i j sij0 of+ (# sij1, uij #) -> (# writeU i j uij sij1, () #)+ ) 0# j () sj1+ , (# sj3, ujj #) <- computeU j j sj2+ , sj4 <- writeU j j ujj sj3+ -> case ujj of+ 0 -> loop+ ( \i _ sij -> (# writeL i j 0 sij, () #)+ ) (j +# 1#) n () sj4+ x -> loop+ ( \i _ sij0 -> case computeL' i j sij0 of+ (# sij1, lij #) -> (# writeL i j (lij / x) sij1, () #)+ ) (j +# 1#) n () sj4+ ) 0# n () s4+ , (# sf0, bl #) <- unsafeFreezeByteArray# mbl sr+ , (# sf1, bu #) <- unsafeFreezeByteArray# mbu sf0+ = (# sf1, (# bu, bl #) #)+++-- | Solve @Ax = b@ problem given LU decomposition of A.+luSolve :: forall (t :: Type) (n :: Nat)+ . ( KnownDim n, Fractional t+ , PrimArray t (Matrix t n n), PrimArray t (Vector t n))+ => LUFact t n -> Vector t n -> Vector t n+luSolve LUFact {..} b = x+ where+ -- Pb = LUx+ pb = luPerm %* b+ n# = case dimVal' @n of W# w -> word2Int# w+ n = I# n#+ -- Ly = Pb+ y :: Vector t n+ y = runST $ do+ my <- newDataFrame+ let ixA (I# i) (I# j) = scalar $ ix# (i *# n# +# j) luLower+ ixB (I# i) = scalar $ ix# i pb+ forM_ [0..n-1] $ \i -> do+ v <- foldM ( \v j -> do+ dj <- readDataFrameOff my j+ return $ v - dj * ixA i j+ ) (ixB i) [0..i-1]+ writeDataFrameOff my i v+ unsafeFreezeDataFrame my+ -- Ux = y+ x = runST $ do+ mx <- newDataFrame+ let ixA (I# i) (I# j) = scalar $ ix# (i *# n# +# j) luUpper+ ixB (I# i) = scalar $ ix# i y+ forM_ [n-1, n-2 .. 0] $ \i -> do+ v <- foldM ( \v j -> do+ dj <- readDataFrameOff mx j+ return $ v - dj * ixA i j+ ) (ixB i) [i+1..n-1]+ writeDataFrameOff mx i (v / ixA i i)+ unsafeFreezeDataFrame mx+++-- | Permute rows that the largest magnitude elements in columns are on diagonals.+--+-- Invariants of result matrix:+-- * forall j >= i: |M[i,i]| >= M[j,i]+-- * if M[i,i] == 0 then forall j >= i: |M[i+1,i+1]| >= M[j,i+1]+pivotMat :: forall (t :: Type) (n :: Nat)+ . (KnownDim n, PrimArray t (Matrix t n n), Ord t, Num t)+ => Matrix t n n -> ( Matrix t n n -- permutated matrix+ , Matrix t n n -- permutation matrix+ , Scalar t -- sign of permutation matrix+ )+pivotMat mat+ = ( let f ( _, [] ) = undefined+ f ( j, i:is )+ | j == n = f (0, is)+ | otherwise = (# (j+1, i:is), ix i j #)+ in case gen# steps f (0,rowOrder) of+ (# _, r #) -> r+ , let f ( _, [] ) = undefined+ f ( j, x:xs )+ | j == n = f (0, xs)+ | otherwise = (# ( j + 1, x:xs), if j == x then 1 else 0 #)+ in case gen# steps f (0,rowOrder) of+ (# _, r #) -> r+ , if countMisordered rowOrder `rem` 2 == 1+ then -1 else 1+ )+ where+ dn = dimVal' @n+ steps = CumulDims [dn * dn, dn, 1]+ -- permuted row ordering+ rowOrder = uncurry fillPass $ searchPass 0 [0..n-1]+ -- matrix size+ n = fromIntegral dn+ n# = case n of I# x -> x+ -- sign of permutations+ countMisordered :: [Int] -> Int+ countMisordered [] = 0+ countMisordered (i:is) = foldl' (\c j -> if i > j then succ c else c) 0 is+ + countMisordered is+ ix (I# i) (I# j) = ix# (i *# n# +# j) mat+ findMax :: Int -> [Int] -> (t, Int)+ findMax j = foldl' (\(ox, oi) i -> let x = abs (ix i j)+ in if x > ox then (x, i)+ else (ox, oi)+ ) (0, 0)+ -- search maximums, leaving Nothing where all rows are 0+ searchPass :: Int -> [Int] -> ([Int], [Maybe Int])+ searchPass j is+ | j == n = (is, [])+ | otherwise = case findMax j is of+ (0, _) -> (Nothing:) <$> searchPass (j+1) is+ (_, i) -> (Just i:) <$> searchPass (j+1) (delete i is)+ -- replace Nothings with remaining row numbers+ fillPass :: [Int] -> [Maybe Int] -> [Int]+ fillPass _ [] = []+ fillPass js (Just i : is) = i : fillPass js is+ fillPass (j:js) (Nothing : is) = j : fillPass js is+ fillPass [] (Nothing : is) = 0 : fillPass [] is
+ src/Numeric/Matrix/Internal/Mat44d.hs view
@@ -0,0 +1,186 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Numeric.Matrix.Internal.Mat44d () where++import qualified Control.Monad.ST as ST+import qualified Numeric.DataFrame.ST as ST+import Numeric.Matrix.Internal+import Numeric.Scalar.Internal+import Numeric.Vector.Internal++{-# INLINE mkMat #-}+mkMat ::+ Double -> Double -> Double -> Double ->+ Double -> Double -> Double -> Double ->+ Double -> Double -> Double -> Double ->+ Double -> Double -> Double -> Double ->+ Mat44d+mkMat+ _11 _12 _13 _14+ _21 _22 _23 _24+ _31 _32 _33 _34+ _41 _42 _43 _44+ = ST.runST $ do+ df <- ST.newDataFrame+ ST.writeDataFrameOff df 0 $ scalar _11+ ST.writeDataFrameOff df 1 $ scalar _12+ ST.writeDataFrameOff df 2 $ scalar _13+ ST.writeDataFrameOff df 3 $ scalar _14+ ST.writeDataFrameOff df 4 $ scalar _21+ ST.writeDataFrameOff df 5 $ scalar _22+ ST.writeDataFrameOff df 6 $ scalar _23+ ST.writeDataFrameOff df 7 $ scalar _24+ ST.writeDataFrameOff df 8 $ scalar _31+ ST.writeDataFrameOff df 9 $ scalar _32+ ST.writeDataFrameOff df 10 $ scalar _33+ ST.writeDataFrameOff df 11 $ scalar _34+ ST.writeDataFrameOff df 12 $ scalar _41+ ST.writeDataFrameOff df 13 $ scalar _42+ ST.writeDataFrameOff df 14 $ scalar _43+ ST.writeDataFrameOff df 15 $ scalar _44+ ST.unsafeFreezeDataFrame df++instance HomTransform4 Double where+ {-# INLINE translate4 #-}+ translate4 (unpackV4# -> (# x, y, z, _ #)) = mkMat+ 1 0 0 0+ 0 1 0 0+ 0 0 1 0+ x y z 1++ {-# INLINE translate3 #-}+ translate3 (unpackV3# -> (# x, y, z #)) = mkMat+ 1 0 0 0+ 0 1 0 0+ 0 0 1 0+ x y z 1++ {-# INLINE rotateX #-}+ rotateX a = mkMat+ 1 0 0 0+ 0 c s 0+ 0 n c 0+ 0 0 0 1+ where+ c = cos a+ s = sin a+ n = -s++ {-# INLINE rotateY #-}+ rotateY a = mkMat+ c 0 n 0+ 0 1 0 0+ s 0 c 0+ 0 0 0 1+ where+ c = cos a+ s = sin a+ n = -s++ {-# INLINE rotateZ #-}+ rotateZ a = mkMat+ c s 0 0+ n c 0 0+ 0 0 1 0+ 0 0 0 1+ where+ c = cos a+ s = sin a+ n = -s++ {-# INLINE rotate #-}+ rotate (unpackV3# -> (# x, y, z #)) a = mkMat+ (c+xxv) (yxv+zs) (zxv-ys) 0+ (xyv-zs) (c+yyv) (zyv+xs) 0+ (xzv+ys) (yzv-xs) (c+zzv) 0+ 0 0 0 1+ where+ c = cos a+ v = 1 - c -- v for versine+ s = sin a+ xxv = x * x * v+ xyv = x * y * v+ xzv = x * z * v+ yxv = xyv+ yyv = y * y * v+ yzv = y * z * v+ zxv = xzv+ zyv = yzv+ zzv = z * z * v+ xs = x * s+ ys = y * s+ zs = z * s++ {-# INLINE rotateEuler #-}+ rotateEuler x y z = mkMat+ (cy*cz) (cx*sz+sx*sy*cz) (sx*sz-cx*sy*cz) 0+ (-cy*sz) (cx*cz-sx*sy*sz) (sx*cz+cx*sy*sz) 0+ sy (-sx*cy) (cx*cy) 0+ 0 0 0 1+ where+ cx = cos x+ sx = sin x+ cy = cos y+ sy = sin y+ cz = cos z+ sz = sin z++ {-# INLINE lookAt #-}+ lookAt up cam foc = mkMat+ xb1 yb1 zb1 0+ xb2 yb2 zb2 0+ xb3 yb3 zb3 0+ tx ty tz 1+ where+ (# xb1, xb2, xb3 #) = unpackV3# xb+ (# yb1, yb2, yb3 #) = unpackV3# yb+ (# zb1, zb2, zb3 #) = unpackV3# zb+ zb = normalized $ cam - foc -- Basis vector for "backward", since +Z is behind the camera+ xb = normalized $ up `cross` zb -- Basis vector for "right"+ yb = zb `cross` xb -- Basis vector for "up"+ ncam = -cam+ tx = unScalar $ xb `dot` ncam+ ty = unScalar $ yb `dot` ncam+ tz = unScalar $ zb `dot` ncam++ {-# INLINE perspective #-}+ perspective n f fovy aspect = mkMat+ dpw 0 0 0+ 0 dph 0 0+ 0 0 a (-1)+ 0 0 b 0+ where+ hpd = tan (fovy * 0.5) -- height/distance+ wpd = aspect * hpd; -- width/distance+ dph = recip hpd -- distance/height+ dpw = recip wpd -- distance/width+ nmf = n - f+ a = (n + f) / nmf+ b = 2 * n * f / nmf++ {-# INLINE orthogonal #-}+ orthogonal n f w h = mkMat+ iw 0 0 0+ 0 ih 0 0+ 0 0 a 0+ 0 0 b 1+ where+ ih = 2 / h+ iw = 2 / w+ nmf = n - f+ a = 2 / nmf+ b = (n + f) / nmf++ {-# INLINE toHomPoint #-}+ toHomPoint (unpackV3# -> (# x, y, z #)) = vec4 x y z 1++ {-# INLINE toHomVector #-}+ toHomVector (unpackV3# -> (# x, y, z #)) = vec4 x y z 0++ {-# INLINE fromHom #-}+ fromHom (unpackV4# -> (# x, y, z, w #))+ | w == 0 = vec3 x y z+ | otherwise = vec3 (x/w) (y/w) (z/w)
+ src/Numeric/Matrix/Internal/Mat44f.hs view
@@ -0,0 +1,186 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Numeric.Matrix.Internal.Mat44f () where++import qualified Control.Monad.ST as ST+import qualified Numeric.DataFrame.ST as ST+import Numeric.Matrix.Internal+import Numeric.Scalar.Internal+import Numeric.Vector.Internal++{-# INLINE mkMat #-}+mkMat ::+ Float -> Float -> Float -> Float ->+ Float -> Float -> Float -> Float ->+ Float -> Float -> Float -> Float ->+ Float -> Float -> Float -> Float ->+ Mat44f+mkMat+ _11 _12 _13 _14+ _21 _22 _23 _24+ _31 _32 _33 _34+ _41 _42 _43 _44+ = ST.runST $ do+ df <- ST.newDataFrame+ ST.writeDataFrameOff df 0 $ scalar _11+ ST.writeDataFrameOff df 1 $ scalar _12+ ST.writeDataFrameOff df 2 $ scalar _13+ ST.writeDataFrameOff df 3 $ scalar _14+ ST.writeDataFrameOff df 4 $ scalar _21+ ST.writeDataFrameOff df 5 $ scalar _22+ ST.writeDataFrameOff df 6 $ scalar _23+ ST.writeDataFrameOff df 7 $ scalar _24+ ST.writeDataFrameOff df 8 $ scalar _31+ ST.writeDataFrameOff df 9 $ scalar _32+ ST.writeDataFrameOff df 10 $ scalar _33+ ST.writeDataFrameOff df 11 $ scalar _34+ ST.writeDataFrameOff df 12 $ scalar _41+ ST.writeDataFrameOff df 13 $ scalar _42+ ST.writeDataFrameOff df 14 $ scalar _43+ ST.writeDataFrameOff df 15 $ scalar _44+ ST.unsafeFreezeDataFrame df++instance HomTransform4 Float where+ {-# INLINE translate4 #-}+ translate4 (unpackV4# -> (# x, y, z, _ #)) = mkMat+ 1 0 0 0+ 0 1 0 0+ 0 0 1 0+ x y z 1++ {-# INLINE translate3 #-}+ translate3 (unpackV3# -> (# x, y, z #)) = mkMat+ 1 0 0 0+ 0 1 0 0+ 0 0 1 0+ x y z 1++ {-# INLINE rotateX #-}+ rotateX a = mkMat+ 1 0 0 0+ 0 c s 0+ 0 n c 0+ 0 0 0 1+ where+ c = cos a+ s = sin a+ n = -s++ {-# INLINE rotateY #-}+ rotateY a = mkMat+ c 0 n 0+ 0 1 0 0+ s 0 c 0+ 0 0 0 1+ where+ c = cos a+ s = sin a+ n = -s++ {-# INLINE rotateZ #-}+ rotateZ a = mkMat+ c s 0 0+ n c 0 0+ 0 0 1 0+ 0 0 0 1+ where+ c = cos a+ s = sin a+ n = -s++ {-# INLINE rotate #-}+ rotate (unpackV3# -> (# x, y, z #)) a = mkMat+ (c+xxv) (yxv+zs) (zxv-ys) 0+ (xyv-zs) (c+yyv) (zyv+xs) 0+ (xzv+ys) (yzv-xs) (c+zzv) 0+ 0 0 0 1+ where+ c = cos a+ v = 1 - c -- v for versine+ s = sin a+ xxv = x * x * v+ xyv = x * y * v+ xzv = x * z * v+ yxv = xyv+ yyv = y * y * v+ yzv = y * z * v+ zxv = xzv+ zyv = yzv+ zzv = z * z * v+ xs = x * s+ ys = y * s+ zs = z * s++ {-# INLINE rotateEuler #-}+ rotateEuler x y z = mkMat+ (cy*cz) (cx*sz+sx*sy*cz) (sx*sz-cx*sy*cz) 0+ (-cy*sz) (cx*cz-sx*sy*sz) (sx*cz+cx*sy*sz) 0+ sy (-sx*cy) (cx*cy) 0+ 0 0 0 1+ where+ cx = cos x+ sx = sin x+ cy = cos y+ sy = sin y+ cz = cos z+ sz = sin z++ {-# INLINE lookAt #-}+ lookAt up cam foc = mkMat+ xb1 yb1 zb1 0+ xb2 yb2 zb2 0+ xb3 yb3 zb3 0+ tx ty tz 1+ where+ (# xb1, xb2, xb3 #) = unpackV3# xb+ (# yb1, yb2, yb3 #) = unpackV3# yb+ (# zb1, zb2, zb3 #) = unpackV3# zb+ zb = normalized $ cam - foc -- Basis vector for "backward", since +Z is behind the camera+ xb = normalized $ up `cross` zb -- Basis vector for "right"+ yb = zb `cross` xb -- Basis vector for "up"+ ncam = -cam+ tx = unScalar $ xb `dot` ncam+ ty = unScalar $ yb `dot` ncam+ tz = unScalar $ zb `dot` ncam++ {-# INLINE perspective #-}+ perspective n f fovy aspect = mkMat+ dpw 0 0 0+ 0 dph 0 0+ 0 0 a (-1)+ 0 0 b 0+ where+ hpd = tan (fovy * 0.5) -- height/distance+ wpd = aspect * hpd; -- width/distance+ dph = recip hpd -- distance/height+ dpw = recip wpd -- distance/width+ nmf = n - f+ a = (n + f) / nmf+ b = 2 * n * f / nmf++ {-# INLINE orthogonal #-}+ orthogonal n f w h = mkMat+ iw 0 0 0+ 0 ih 0 0+ 0 0 a 0+ 0 0 b 1+ where+ ih = 2 / h+ iw = 2 / w+ nmf = n - f+ a = 2 / nmf+ b = (n + f) / nmf++ {-# INLINE toHomPoint #-}+ toHomPoint (unpackV3# -> (# x, y, z #)) = vec4 x y z 1++ {-# INLINE toHomVector #-}+ toHomVector (unpackV3# -> (# x, y, z #)) = vec4 x y z 0++ {-# INLINE fromHom #-}+ fromHom (unpackV4# -> (# x, y, z, w #))+ | w == 0 = vec3 x y z+ | otherwise = vec3 (x/w) (y/w) (z/w)
− src/Numeric/Matrix/Mat44d.hs
@@ -1,196 +0,0 @@-{-# LANGUAGE MagicHash #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Numeric.Matrix.Mat44d () where--import qualified Control.Monad.ST as ST-import GHC.Exts-import Numeric.DataFrame.Internal.Array.Family.DoubleX3-import Numeric.DataFrame.Internal.Array.Family.DoubleX4-import qualified Numeric.DataFrame.ST as ST-import Numeric.DataFrame.SubSpace-import Numeric.DataFrame.Type-import Numeric.Matrix.Class-import Numeric.Scalar-import Numeric.Vector--{-# INLINE mat44d #-}-mat44d ::- Scd -> Scd -> Scd -> Scd ->- Scd -> Scd -> Scd -> Scd ->- Scd -> Scd -> Scd -> Scd ->- Scd -> Scd -> Scd -> Scd ->- Mat44d-mat44d- _11 _12 _13 _14- _21 _22 _23 _24- _31 _32 _33 _34- _41 _42 _43 _44- = ST.runST $ do- df <- ST.newDataFrame- ST.writeDataFrameOff df 0 _11- ST.writeDataFrameOff df 1 _21- ST.writeDataFrameOff df 2 _31- ST.writeDataFrameOff df 3 _41- ST.writeDataFrameOff df 4 _12- ST.writeDataFrameOff df 5 _22- ST.writeDataFrameOff df 6 _32- ST.writeDataFrameOff df 7 _42- ST.writeDataFrameOff df 8 _13- ST.writeDataFrameOff df 9 _23- ST.writeDataFrameOff df 10 _33- ST.writeDataFrameOff df 11 _43- ST.writeDataFrameOff df 12 _14- ST.writeDataFrameOff df 13 _24- ST.writeDataFrameOff df 14 _34- ST.writeDataFrameOff df 15 _44- ST.unsafeFreezeDataFrame df- -instance HomTransform4 Double where- {-# INLINE translate4 #-}- translate4 (SingleFrame (DoubleX4# x# y# z# _)) = mat44d- 1 0 0 x- 0 1 0 y- 0 0 1 z- 0 0 0 1- where- x = scalar $ D# x#- y = scalar $ D# y#- z = scalar $ D# z#-- {-# INLINE translate3 #-}- translate3 (SingleFrame (DoubleX3# x# y# z#)) = mat44d- 1 0 0 x- 0 1 0 y- 0 0 1 z- 0 0 0 1- where- x = scalar $ D# x#- y = scalar $ D# y#- z = scalar $ D# z#-- {-# INLINE rotateX #-}- rotateX a = mat44d- 1 0 0 0- 0 c n 0- 0 s c 0- 0 0 0 1- where- c = scalar $ cos a- s = scalar $ sin a- n = -s-- {-# INLINE rotateY #-}- rotateY a = mat44d- c 0 s 0- 0 1 0 0- n 0 c 0- 0 0 0 1- where- c = scalar $ cos a- s = scalar $ sin a- n = -s-- {-# INLINE rotateZ #-}- rotateZ a = mat44d- c n 0 0- s c 0 0- 0 0 1 0- 0 0 0 1- where- c = scalar $ cos a- s = scalar $ sin a- n = -s-- {-# INLINE rotate #-}- rotate (SingleFrame (DoubleX3# x# y# z#)) a = mat44d- (c+xxv) (xyv-zs) (xzv+ys) 0- (yxv+zs) (c+yyv) (yzv-xs) 0- (zxv-ys) (zyv+xs) (c+zzv) 0- 0 0 0 1- where- c = scalar $ cos a- v = 1 - c -- v for versine- s = scalar $ sin a- x = scalar $ D# x#- y = scalar $ D# y#- z = scalar $ D# z#- xxv = x * x * v- xyv = x * y * v- xzv = x * z * v- yxv = xyv- yyv = y * y * v- yzv = y * z * v- zxv = xzv- zyv = yzv- zzv = z * z * v- xs = x * s- ys = y * s- zs = z * s-- {-# INLINE rotateEuler #-}- rotateEuler x y z = mat44d- (cy*cz) (-cy*sz) sy 0- (cx*sz+sx*sy*cz) (cx*cz-sx*sy*sz) (-sx*cy) 0- (sx*sz-cx*sy*cz) (sx*cz+cx*sy*sz) (cx*cy) 0- 0 0 0 1- where- cx = scalar $ cos x- sx = scalar $ sin x- cy = scalar $ cos y- sy = scalar $ sin y- cz = scalar $ cos z- sz = scalar $ sin z-- {-# INLINE lookAt #-}- lookAt up cam foc = mat44d- (xb!1) (xb!2) (xb!3) tx- (yb!1) (yb!2) (yb!3) ty- (zb!1) (zb!2) (zb!3) tz- 0 0 0 1- where- zb = normalized $ cam - foc -- Basis vector for "backward", since +Z is behind the camera- xb = normalized $ up `cross` zb -- Basis vector for "right"- yb = zb `cross` xb -- Basis vector for "up"- ncam = -cam- tx = xb `dot` ncam- ty = yb `dot` ncam- tz = zb `dot` ncam-- {-# INLINE perspective #-}- perspective n f fovy aspect = mat44d- dpw 0 0 0- 0 dph 0 0- 0 0 a b- 0 0 (-1) 0- where- hpd = tan (fovy * 0.5) -- height/distance- wpd = aspect * hpd; -- width/distance- dph = scalar $ 1 / hpd -- distance/height- dpw = scalar $ 1 / wpd -- distance/width- nmf = n - f- a = scalar $ (n + f) / nmf- b = scalar $ 2 * n * f / nmf-- {-# INLINE orthogonal #-}- orthogonal n f w h = mat44d- iw 0 0 0- 0 ih 0 0- 0 0 a b- 0 0 0 1- where- ih = scalar $ 2 / h- iw = scalar $ 2 / w- nmf = n - f- a = scalar $ 2 / nmf- b = scalar $ (n + f) / nmf-- {-# INLINE toHomPoint #-}- toHomPoint (SingleFrame (DoubleX3# x# y# z#)) = SingleFrame (DoubleX4# x# y# z# 1.0##)-- {-# INLINE toHomVector #-}- toHomVector (SingleFrame (DoubleX3# x# y# z#)) = SingleFrame (DoubleX4# x# y# z# 0.0##)-- {-# INLINE fromHom #-}- fromHom (SingleFrame (DoubleX4# x# y# z# 0.0##)) = SingleFrame (DoubleX3# x# y# z#)- fromHom (SingleFrame (DoubleX4# x# y# z# w#)) = SingleFrame (DoubleX3# (x# /## w#) (y# /## w#) (z# /## w#))
− src/Numeric/Matrix/Mat44f.hs
@@ -1,196 +0,0 @@-{-# LANGUAGE MagicHash #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Numeric.Matrix.Mat44f () where--import qualified Control.Monad.ST as ST-import GHC.Exts-import Numeric.DataFrame.Internal.Array.Family.FloatX3-import Numeric.DataFrame.Internal.Array.Family.FloatX4-import qualified Numeric.DataFrame.ST as ST-import Numeric.DataFrame.SubSpace-import Numeric.DataFrame.Type-import Numeric.Matrix.Class-import Numeric.Scalar-import Numeric.Vector--{-# INLINE mat44f #-}-mat44f ::- Scf -> Scf -> Scf -> Scf ->- Scf -> Scf -> Scf -> Scf ->- Scf -> Scf -> Scf -> Scf ->- Scf -> Scf -> Scf -> Scf ->- Mat44f-mat44f- _11 _12 _13 _14- _21 _22 _23 _24- _31 _32 _33 _34- _41 _42 _43 _44- = ST.runST $ do- df <- ST.newDataFrame- ST.writeDataFrameOff df 0 _11- ST.writeDataFrameOff df 1 _21- ST.writeDataFrameOff df 2 _31- ST.writeDataFrameOff df 3 _41- ST.writeDataFrameOff df 4 _12- ST.writeDataFrameOff df 5 _22- ST.writeDataFrameOff df 6 _32- ST.writeDataFrameOff df 7 _42- ST.writeDataFrameOff df 8 _13- ST.writeDataFrameOff df 9 _23- ST.writeDataFrameOff df 10 _33- ST.writeDataFrameOff df 11 _43- ST.writeDataFrameOff df 12 _14- ST.writeDataFrameOff df 13 _24- ST.writeDataFrameOff df 14 _34- ST.writeDataFrameOff df 15 _44- ST.unsafeFreezeDataFrame df- -instance HomTransform4 Float where- {-# INLINE translate4 #-}- translate4 (SingleFrame (FloatX4# x# y# z# _)) = mat44f- 1 0 0 x- 0 1 0 y- 0 0 1 z- 0 0 0 1- where- x = scalar $ F# x#- y = scalar $ F# y#- z = scalar $ F# z#-- {-# INLINE translate3 #-}- translate3 (SingleFrame (FloatX3# x# y# z#)) = mat44f- 1 0 0 x- 0 1 0 y- 0 0 1 z- 0 0 0 1- where- x = scalar $ F# x#- y = scalar $ F# y#- z = scalar $ F# z#-- {-# INLINE rotateX #-}- rotateX a = mat44f- 1 0 0 0- 0 c n 0- 0 s c 0- 0 0 0 1- where- c = scalar $ cos a- s = scalar $ sin a- n = -s-- {-# INLINE rotateY #-}- rotateY a = mat44f- c 0 s 0- 0 1 0 0- n 0 c 0- 0 0 0 1- where- c = scalar $ cos a- s = scalar $ sin a- n = -s-- {-# INLINE rotateZ #-}- rotateZ a = mat44f- c n 0 0- s c 0 0- 0 0 1 0- 0 0 0 1- where- c = scalar $ cos a- s = scalar $ sin a- n = -s-- {-# INLINE rotate #-}- rotate (SingleFrame (FloatX3# x# y# z#)) a = mat44f- (c+xxv) (xyv-zs) (xzv+ys) 0- (yxv+zs) (c+yyv) (yzv-xs) 0- (zxv-ys) (zyv+xs) (c+zzv) 0- 0 0 0 1- where- c = scalar $ cos a- v = 1 - c -- v for versine- s = scalar $ sin a- x = scalar $ F# x#- y = scalar $ F# y#- z = scalar $ F# z#- xxv = x * x * v- xyv = x * y * v- xzv = x * z * v- yxv = xyv- yyv = y * y * v- yzv = y * z * v- zxv = xzv- zyv = yzv- zzv = z * z * v- xs = x * s- ys = y * s- zs = z * s-- {-# INLINE rotateEuler #-}- rotateEuler x y z = mat44f- (cy*cz) (-cy*sz) sy 0- (cx*sz+sx*sy*cz) (cx*cz-sx*sy*sz) (-sx*cy) 0- (sx*sz-cx*sy*cz) (sx*cz+cx*sy*sz) (cx*cy) 0- 0 0 0 1- where- cx = scalar $ cos x- sx = scalar $ sin x- cy = scalar $ cos y- sy = scalar $ sin y- cz = scalar $ cos z- sz = scalar $ sin z-- {-# INLINE lookAt #-}- lookAt up cam foc = mat44f- (xb!1) (xb!2) (xb!3) tx- (yb!1) (yb!2) (yb!3) ty- (zb!1) (zb!2) (zb!3) tz- 0 0 0 1- where- zb = normalized $ cam - foc -- Basis vector for "backward", since +Z is behind the camera- xb = normalized $ up `cross` zb -- Basis vector for "right"- yb = zb `cross` xb -- Basis vector for "up"- ncam = -cam- tx = xb `dot` ncam- ty = yb `dot` ncam- tz = zb `dot` ncam-- {-# INLINE perspective #-}- perspective n f fovy aspect = mat44f- dpw 0 0 0- 0 dph 0 0- 0 0 a b- 0 0 (-1) 0- where- hpd = tan (fovy * 0.5) -- height/distance- wpd = aspect * hpd; -- width/distance- dph = scalar $ 1 / hpd -- distance/height- dpw = scalar $ 1 / wpd -- distance/width- nmf = n - f- a = scalar $ (n + f) / nmf- b = scalar $ 2 * n * f / nmf-- {-# INLINE orthogonal #-}- orthogonal n f w h = mat44f- iw 0 0 0- 0 ih 0 0- 0 0 a b- 0 0 0 1- where- ih = scalar $ 2 / h- iw = scalar $ 2 / w- nmf = n - f- a = scalar $ 2 / nmf- b = scalar $ (n + f) / nmf-- {-# INLINE toHomPoint #-}- toHomPoint (SingleFrame (FloatX3# x# y# z#)) = SingleFrame (FloatX4# x# y# z# 1.0#)-- {-# INLINE toHomVector #-}- toHomVector (SingleFrame (FloatX3# x# y# z#)) = SingleFrame (FloatX4# x# y# z# 0.0#)-- {-# INLINE fromHom #-}- fromHom (SingleFrame (FloatX4# x# y# z# 0.0#)) = SingleFrame (FloatX3# x# y# z#)- fromHom (SingleFrame (FloatX4# x# y# z# w#)) = SingleFrame (FloatX3# (x# `divideFloat#` w#) (y# `divideFloat#` w#) (z# `divideFloat#` w#))
src/Numeric/PrimBytes.hs view
@@ -1,1428 +1,1792 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}--- {-# LANGUAGE IncoherentInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UnboxedTuples #-}-{-# LANGUAGE UndecidableInstances #-}--module Numeric.PrimBytes- ( PrimBytes- ( getBytes, fromBytes, readBytes, writeBytes, byteSize, byteAlign, byteOffset- , indexArray, readArray, writeArray, readAddr, writeAddr)- , PrimTag (..), primTag- ) where--#include "MachDeps.h"--import Data.Proxy (Proxy (..))-import GHC.Exts-import GHC.Generics-import GHC.Int-import GHC.Word-import Numeric.Dimensions.Idxs-import qualified Numeric.Tuple.Lazy as TL-import qualified Numeric.Tuple.Strict as TS-import qualified Numeric.Type.List as L---- | Facilities to convert to and from raw byte array.-class PrimTagged a => PrimBytes a where- -- | Store content of a data type in a primitive byte array- -- Should be used together with @byteOffset@ function.- getBytes :: a -> ByteArray#- -- | Load content of a data type from a primitive byte array- fromBytes :: Int# -- ^ offset in bytes- -> ByteArray#- -> a- -- | Read data from a mutable byte array given an offset in bytes- readBytes :: MutableByteArray# s -- ^ source array- -> Int# -- ^ byte offset of the source array- -> State# s -> (# State# s, a #)- -- | Write data into a mutable byte array at a given position (offset in bytes)- writeBytes :: MutableByteArray# s -- ^ destination array- -> Int# -- ^ byte offset of the destination array- -> a -- ^ data to write into array- -> State# s -> State# s- -- | Read data from a specified address- readAddr :: Addr# -> State# s -> (# State# s, a #)- -- | Write data to a specified address- writeAddr :: a -> Addr# -> State# s -> State# s- -- | Size of a data type in bytes- byteSize :: a -> Int#- -- | Alignment of a data type in bytes.- -- @byteOffset@ should be multiple of this value.- byteAlign :: a -> Int#- -- | Offset of the data in a byte array used to store the data,- -- measured in bytes.- -- Should be used together with @getBytes@ function.- -- Unless in case of special data types represented by ByteArrays,- -- it is equal to zero.- byteOffset :: a -> Int#-- -- | Index array given an element offset.- --- -- > indexArray arr i = fromBytes ( i *# byteSize t) arr- indexArray :: ByteArray# -> Int# -> a- indexArray ba i = fromBytes (i *# byteSize @a undefined) ba- {-# INLINE indexArray #-}-- -- | Read a mutable array given an element offset.- --- -- > readArray arr i = readBytes arr ( i *# byteSize t)- readArray :: MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)- readArray ba i = readBytes ba (i *# byteSize @a undefined)- {-# INLINE readArray #-}-- -- | Write a mutable array given an element offset.- --- -- > writeArray arr i = writeBytes arr ( i *# byteSize t)- writeArray :: MutableByteArray# s -> Int# -> a -> State# s -> State# s- writeArray ba i = writeBytes ba (i *# byteSize @a undefined)- {-# INLINE writeArray #-}---- default getBytes :: (Generic a, GPrimBytes (Rep a)) => a -> ByteArray#- getBytes a = ggetBytes (from a)- {-# INLINE getBytes #-}-- default fromBytes :: (Generic a, GPrimBytes (Rep a))- => Int# -> ByteArray# -> a- fromBytes i arr = to (gfromBytes 0## i arr)- {-# INLINE fromBytes #-}-- default readBytes :: (Generic a, GPrimBytes (Rep a))- => MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)- readBytes mba i s = case greadBytes 0## mba i s of- (# s', x #) -> (# s', to x #)- {-# INLINE readBytes #-}-- default writeBytes :: (Generic a, GPrimBytes (Rep a))- => MutableByteArray# s -> Int# -> a -> State# s -> State# s- writeBytes mba i = gwriteBytes 0## mba i . from- {-# INLINE writeBytes #-}-- default readAddr :: (Generic a, GPrimBytes (Rep a))- => Addr# -> State# s -> (# State# s, a #)- readAddr a s = case greadAddr 0## a s of- (# s', x #) -> (# s', to x #)- {-# INLINE readAddr #-}-- default writeAddr :: (Generic a, GPrimBytes (Rep a))- => a -> Addr# -> State# s -> State# s- writeAddr = gwriteAddr 0## . from- {-# INLINE writeAddr #-}--- default byteSize :: (Generic a, GPrimBytes (Rep a))- => a -> Int#- byteSize a = gbyteSize (from a)- {-# INLINE byteSize #-}-- default byteAlign :: (Generic a, GPrimBytes (Rep a))- => a -> Int#- byteAlign a = gbyteAlign (from a)- {-# INLINE byteAlign #-}-- default byteOffset :: (Generic a, GPrimBytes (Rep a))- => a -> Int#- byteOffset a = gbyteOffset (from a)- {-# INLINE byteOffset #-}----- | Deriving `PrimBytes` using generics-class GPrimBytes f where- ggetBytes :: f p -> ByteArray#- gfromBytes :: Word# -- ^ Starting value of a constructor tag- -> Int# -> ByteArray# -> f p- greadBytes :: Word# -- ^ Starting value of a constructor tag- -> MutableByteArray# s -> Int# -> State# s -> (# State# s, f p #)- gwriteBytes :: Word# -- ^ Starting value of a constructor tag- -> MutableByteArray# s -> Int# -> f p -> State# s -> State# s- greadAddr :: Word# -- ^ Starting value of a constructor tag- -> Addr# -> State# s -> (# State# s, f p #)- gwriteAddr :: Word# -- ^ Starting value of a constructor tag- -> f p -> Addr# -> State# s -> State# s- gbyteSize :: f p -> Int#- gbyteAlign :: f p -> Int#- gbyteOffset :: f p -> Int#- -- | Number of constructors in the tree of a sum type.- -- This is equal to one for all other types.- gconTags :: f p -> Word#---instance GPrimBytes V1 where- -- Probably, this is illegal due to zero size of the array.- -- There is no bottom to put here, but one should not call this anyway.- ggetBytes _ = case runRW#- ( \s0 -> case newByteArray# 0# s0 of- (# s1, marr #) -> unsafeFreezeByteArray# marr s1- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ _ _ = undefined- {-# INLINE gfromBytes #-}- greadBytes _ _ _ s = (# s, undefined #)- {-# INLINE greadBytes #-}- gwriteBytes _ _ _ _ s = s- {-# INLINE gwriteBytes #-}- greadAddr _ _ s = (# s, undefined #)- {-# INLINE greadAddr #-}- gwriteAddr _ _ _ s = s- {-# INLINE gwriteAddr #-}- gbyteSize _ = 0#- {-# INLINE gbyteSize #-}- gbyteAlign _ = 1#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 1##- {-# INLINE gconTags #-}--instance GPrimBytes U1 where- -- Probably, this is illegal due to zero size of the array.- -- There is no bottom to put here, but one should not call this anyway.- ggetBytes _ = case runRW#- ( \s0 -> case newByteArray# 0# s0 of- (# s1, marr #) -> unsafeFreezeByteArray# marr s1- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ _ _ = U1- {-# INLINE gfromBytes #-}- greadBytes _ _ _ s = (# s, U1 #)- {-# INLINE greadBytes #-}- gwriteBytes _ _ _ _ s = s- {-# INLINE gwriteBytes #-}- greadAddr _ _ s = (# s, U1 #)- {-# INLINE greadAddr #-}- gwriteAddr _ _ _ s = s- {-# INLINE gwriteAddr #-}- gbyteSize _ = 0#- {-# INLINE gbyteSize #-}- gbyteAlign _ = 1#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 1##- {-# INLINE gconTags #-}--instance PrimBytes a => GPrimBytes (K1 i a) where- ggetBytes ~(K1 a) = getBytes a- {-# NOINLINE ggetBytes #-}- gfromBytes _ i ba = K1 (fromBytes i ba)- {-# INLINE gfromBytes #-}- greadBytes _ = unsafeCoerce# (readBytes @a)- {-# INLINE greadBytes #-}- gwriteBytes _ mba i ~(K1 a) = writeBytes mba i a- {-# INLINE gwriteBytes #-}- greadAddr _ = unsafeCoerce# (readAddr @a)- {-# INLINE greadAddr #-}- gwriteAddr _ ~(K1 a) = writeAddr a- {-# INLINE gwriteAddr #-}- gbyteSize ~(K1 a) = byteSize a- {-# INLINE gbyteSize #-}- gbyteAlign ~(K1 a) = byteAlign a- {-# INLINE gbyteAlign #-}- gbyteOffset ~(K1 a) = byteOffset a- {-# INLINE gbyteOffset #-}- gconTags _ = 1##- {-# INLINE gconTags #-}--instance GPrimBytes f => GPrimBytes (M1 i c f) where- ggetBytes ~(M1 a) = ggetBytes a- {-# NOINLINE ggetBytes #-}- gfromBytes t i ba = M1 (gfromBytes t i ba)- {-# INLINE gfromBytes #-}- greadBytes = unsafeCoerce# (greadBytes @f)- {-# INLINE greadBytes #-}- gwriteBytes t mba i ~(M1 a) = gwriteBytes t mba i a- {-# INLINE gwriteBytes #-}- greadAddr = unsafeCoerce# (greadAddr @f)- {-# INLINE greadAddr #-}- gwriteAddr t ~(M1 a) = gwriteAddr t a- {-# INLINE gwriteAddr #-}- gbyteSize ~(M1 a) = gbyteSize a- {-# INLINE gbyteSize #-}- gbyteAlign ~(M1 a) = gbyteAlign a- {-# INLINE gbyteAlign #-}- gbyteOffset ~(M1 a) = gbyteOffset a- {-# INLINE gbyteOffset #-}- gconTags ~(M1 a) = gconTags a- {-# INLINE gconTags #-}---instance (GPrimBytes f, GPrimBytes g) => GPrimBytes (f :*: g) where- -- | This function return not pinned byte array, which is aligned to- -- @SIZEOF_HSWORD@.- -- Thus, it ignores alignment of the underlying data type if it is larger.- -- However, alignment calculation still makes sense for data types- -- that are smaller than @SIZEOF_HSWORD@ bytes: they are packed more densely.- ggetBytes xy = case runRW#- ( \s0 -> case newByteArray# (gbyteSize xy) s0 of- (# s1, marr #) -> unsafeFreezeByteArray# marr- (gwriteBytes 0## marr 0# xy s1)- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ i ba = x :*: y- where- x = gfromBytes 0## i ba- y = gfromBytes 0## (i +# roundUpInt# (gbyteSize x) (gbyteAlign y)) ba- {-# INLINE gfromBytes #-}- greadBytes _ mba i s0 = case greadBytes 0## mba i s0 of- (# s1, x #) -> case greadBytes 0## mba- (i +# roundUpInt# (gbyteSize x)- (gbyteAlign @g undefined)- ) s1 of- (# s2, y #) -> (# s2, x :*: y #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off ~(x :*: y) s =- gwriteBytes 0## mba (off +# roundUpInt# (gbyteSize x) (gbyteAlign y)) y- (gwriteBytes 0## mba off x s)- {-# INLINE gwriteBytes #-}- greadAddr _ addr s0 = case greadAddr 0## addr s0 of- (# s1, x #) -> case greadAddr 0##- (plusAddr# addr- (roundUpInt# (gbyteSize x)- (gbyteAlign @g undefined))- ) s1 of- (# s2, y #) -> (# s2, x :*: y #)- {-# INLINE greadAddr #-}- gwriteAddr _ ~(x :*: y) addr s =- gwriteAddr 0## y (plusAddr# addr (roundUpInt# (gbyteSize x) (gbyteAlign y)))- (gwriteAddr 0## x addr s)- {-# INLINE gwriteAddr #-}- gbyteSize ~(x :*: y)- = gbyteSize y +# roundUpInt# (gbyteSize x) (gbyteAlign y)- {-# INLINE gbyteSize #-}- gbyteAlign ~(x :*: y) = maxInt# (gbyteAlign x) (gbyteAlign y)- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 1##- {-# INLINE gconTags #-}----- | Reserve 4 bytes for tag and try to pack alternatives as good as possible.-instance (GPrimBytes f, GPrimBytes g) => GPrimBytes (f :+: g) where- ggetBytes xy = case runRW#- ( \s0 -> case newByteArray# (gbyteSize xy) s0 of- (# s1, marr #) -> unsafeFreezeByteArray# marr- (gwriteBytes 0## marr 0# xy s1)- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes toff off ba- = case (# gconTags (undefined :: f a)- , gconTags (undefined :: g a)- , indexWord32Array# ba (uncheckedIShiftRL# off 2#)- `minusWord#` toff- #) of- (# 1##, _ , 0## #) -> L1 (gfromBytes 0## (off +# 4#) ba)- (# cl , 1##, t #)- | isTrue# (eqWord# cl t) -> R1 (gfromBytes 0## (off +# 4#) ba)- (# cl , _ , t #)- | isTrue# (geWord# cl t) -> L1 (gfromBytes toff off ba)- | otherwise -> R1 (gfromBytes (plusWord# toff cl) off ba)- {-# INLINE gfromBytes #-}- greadBytes toff mba off s0- = case readWord32Array# mba (uncheckedIShiftRL# off 2#) s0 of- (# s1, tval #) -> case (# gconTags (undefined :: f a)- , gconTags (undefined :: g a)- , tval `minusWord#` toff- #) of- (# 1##, _ , 0## #) -> case greadBytes 0## mba (off +# 4#) s1 of- (# s2, r #) -> (# s2, L1 r #)- (# cl , 1##, t #)- | isTrue# (eqWord# cl t) -> case greadBytes 0## mba (off +# 4#) s1 of- (# s2, r #) -> (# s2, R1 r #)- (# cl , _ , t #)- | isTrue# (geWord# cl t) -> case greadBytes toff mba off s1 of- (# s2, r #) -> (# s2, L1 r #)- | otherwise -> case greadBytes (plusWord# toff cl) mba off s1 of- (# s2, r #) -> (# s2, R1 r #)- {-# INLINE greadBytes #-}- gwriteBytes t mba off (L1 x) s- = case gconTags x of- 1## -> gwriteBytes 0## mba (off +# 4#) x- (writeWord32Array# mba (uncheckedIShiftRL# off 2#) t s)- _ -> gwriteBytes t mba off x s- gwriteBytes t mba off xy@(R1 y) s- = case (# gconTags y, plusWord# t (gconTags (undef1 @f xy)) #) of- (# 1## , t' #) -> gwriteBytes 0## mba (off +# 4#) y- (writeWord32Array# mba (uncheckedIShiftRL# off 2#) t' s)- (# _ , t' #) -> gwriteBytes t' mba off y s- {-# INLINE gwriteBytes #-}- greadAddr toff addr s0- = case readWord32OffAddr# addr 0# s0 of- (# s1, tval #) -> case (# gconTags (undefined :: f a)- , gconTags (undefined :: g a)- , tval `minusWord#` toff- #) of- (# 1##, _ , 0## #) -> case greadAddr 0## (plusAddr# addr 4#) s1 of- (# s2, r #) -> (# s2, L1 r #)- (# cl , 1##, t #)- | isTrue# (eqWord# cl t) -> case greadAddr 0## (plusAddr# addr 4#) s1 of- (# s2, r #) -> (# s2, R1 r #)- (# cl , _ , t #)- | isTrue# (geWord# cl t) -> case greadAddr toff addr s1 of- (# s2, r #) -> (# s2, L1 r #)- | otherwise -> case greadAddr (plusWord# toff cl) addr s1 of- (# s2, r #) -> (# s2, R1 r #)- {-# INLINE greadAddr #-}- gwriteAddr t (L1 x) addr s- = case gconTags x of- 1## -> gwriteAddr 0## x (plusAddr# addr 4#)- (writeWord32OffAddr# addr 0# t s)- _ -> gwriteAddr t x addr s- gwriteAddr t xy@(R1 y) addr s- = case (# gconTags y, plusWord# t (gconTags (undef1 @f xy)) #) of- (# 1## , t' #) -> gwriteAddr 0## y (plusAddr# addr 4#)- (writeWord32OffAddr# addr 0# t' s)- (# _ , t' #) -> gwriteAddr t' y addr s- {-# INLINE gwriteAddr #-}- gbyteSize xy = maxInt#- (roundUpInt# 4# (gbyteAlign x) +# gbyteSize x)- (roundUpInt# 4# (gbyteAlign y) +# gbyteSize y)- where- x = undef1 @f xy- y = undef1 @g xy- {-# INLINE gbyteSize #-}- gbyteAlign xy = maxInt# 4# ( maxInt# (gbyteAlign (undef1 @f xy))- (gbyteAlign (undef1 @g xy))- )- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags xy = gconTags (undef1 @f xy) `plusWord#` gconTags (undef1 @g xy)- {-# INLINE gconTags #-}--maxInt# :: Int# -> Int# -> Int#-maxInt# a b | isTrue# (a ># b) = a- | otherwise = b--roundUpInt# :: Int# -> Int# -> Int#-roundUpInt# a b = case remInt# a b of- 0# -> a- q -> a +# b -# q-{-# INLINE roundUpInt# #-}--undef1 :: forall p q a . q a -> p a-undef1 = const undefined-{-# INLINE undef1 #-}----#if SIZEOF_HSWORD == 4-#define OFFSHIFT_W 2-#else-#define OFFSHIFT_W 3-#endif--instance GPrimBytes (URec Word) where- ggetBytes x = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSWORD# s0 of- (# s1, marr #) -> case writeWordArray# marr 0# (uWord# x) s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ off ba- = UWord (indexWordArray# ba (uncheckedIShiftRL# off OFFSHIFT_W#))- {-# INLINE gfromBytes #-}- greadBytes _ mba off s- = case readWordArray# mba (uncheckedIShiftRL# off OFFSHIFT_W#) s of- (# s1, r #) -> (# s1, UWord r #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off x- = writeWordArray# mba (uncheckedIShiftRL# off OFFSHIFT_W#) (uWord# x)- {-# INLINE gwriteBytes #-}- greadAddr _ a s- = case readWordOffAddr# a 0# s of (# s', x #) -> (# s', UWord x #)- {-# INLINE greadAddr #-}- gwriteAddr _ x a- = writeWordOffAddr# a 0# (uWord# x)- {-# INLINE gwriteAddr #-}- gbyteSize _ = SIZEOF_HSWORD#- {-# INLINE gbyteSize #-}- gbyteAlign _ = ALIGNMENT_HSWORD#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 0##- {-# INLINE gconTags #-}--#if SIZEOF_HSINT == 4-#define OFFSHIFT_I 2-#else-#define OFFSHIFT_I 3-#endif--instance GPrimBytes (URec Int) where- ggetBytes x = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSINT# s0 of- (# s1, marr #) -> case writeIntArray# marr 0# (uInt# x) s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ off ba- = UInt (indexIntArray# ba (uncheckedIShiftRL# off OFFSHIFT_I#))- {-# INLINE gfromBytes #-}- greadBytes _ mba off s- = case readIntArray# mba (uncheckedIShiftRL# off OFFSHIFT_I#) s of- (# s1, r #) -> (# s1, UInt r #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off x- = writeIntArray# mba (uncheckedIShiftRL# off OFFSHIFT_I#) (uInt# x)- {-# INLINE gwriteBytes #-}- greadAddr _ a s- = case readIntOffAddr# a 0# s of (# s', x #) -> (# s', UInt x #)- {-# INLINE greadAddr #-}- gwriteAddr _ x a- = writeIntOffAddr# a 0# (uInt# x)- {-# INLINE gwriteAddr #-}- gbyteSize _ = SIZEOF_HSINT#- {-# INLINE gbyteSize #-}- gbyteAlign _ = ALIGNMENT_HSINT#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 0##- {-# INLINE gconTags #-}---#if SIZEOF_HSFLOAT == 4-#define OFFSHIFT_F 2-#else-#define OFFSHIFT_F 3-#endif--instance GPrimBytes (URec Float) where- ggetBytes x = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSFLOAT# s0 of- (# s1, marr #) -> case writeFloatArray# marr 0# (uFloat# x) s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ off ba- = UFloat (indexFloatArray# ba (uncheckedIShiftRL# off OFFSHIFT_F#))- {-# INLINE gfromBytes #-}- greadBytes _ mba off s- = case readFloatArray# mba (uncheckedIShiftRL# off OFFSHIFT_F#) s of- (# s1, r #) -> (# s1, UFloat r #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off x- = writeFloatArray# mba (uncheckedIShiftRL# off OFFSHIFT_F#) (uFloat# x)- {-# INLINE gwriteBytes #-}- greadAddr _ a s- = case readFloatOffAddr# a 0# s of (# s', x #) -> (# s', UFloat x #)- {-# INLINE greadAddr #-}- gwriteAddr _ x a- = writeFloatOffAddr# a 0# (uFloat# x)- {-# INLINE gwriteAddr #-}- gbyteSize _ = SIZEOF_HSFLOAT#- {-# INLINE gbyteSize #-}- gbyteAlign _ = ALIGNMENT_HSFLOAT#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 0##- {-# INLINE gconTags #-}--#if SIZEOF_HSDOUBLE == 4-#define OFFSHIFT_D 2-#else-#define OFFSHIFT_D 3-#endif--instance GPrimBytes (URec Double) where- ggetBytes x = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSDOUBLE# s0 of- (# s1, marr #) -> case writeDoubleArray# marr 0# (uDouble# x) s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ off ba- = UDouble (indexDoubleArray# ba (uncheckedIShiftRL# off OFFSHIFT_D#))- {-# INLINE gfromBytes #-}- greadBytes _ mba off s- = case readDoubleArray# mba (uncheckedIShiftRL# off OFFSHIFT_D#) s of- (# s1, r #) -> (# s1, UDouble r #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off x- = writeDoubleArray# mba (uncheckedIShiftRL# off OFFSHIFT_D#) (uDouble# x)- {-# INLINE gwriteBytes #-}- greadAddr _ a s- = case readDoubleOffAddr# a 0# s of (# s', x #) -> (# s', UDouble x #)- {-# INLINE greadAddr #-}- gwriteAddr _ x a- = writeDoubleOffAddr# a 0# (uDouble# x)- {-# INLINE gwriteAddr #-}- gbyteSize _ = SIZEOF_HSDOUBLE#- {-# INLINE gbyteSize #-}- gbyteAlign _ = ALIGNMENT_HSDOUBLE#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 0##- {-# INLINE gconTags #-}--#if SIZEOF_HSCHAR == 2-#define OFFSHIFT_C 1-#elif SIZEOF_HSCHAR == 4-#define OFFSHIFT_C 2-#else-#define OFFSHIFT_C 3-#endif--instance GPrimBytes (URec Char) where- ggetBytes x = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSCHAR# s0 of- (# s1, marr #) -> case writeCharArray# marr 0# (uChar# x) s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ off ba- = UChar (indexCharArray# ba (uncheckedIShiftRL# off OFFSHIFT_C#))- {-# INLINE gfromBytes #-}- greadBytes _ mba off s- = case readCharArray# mba (uncheckedIShiftRL# off OFFSHIFT_C#) s of- (# s1, r #) -> (# s1, UChar r #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off x- = writeCharArray# mba (uncheckedIShiftRL# off OFFSHIFT_C#) (uChar# x)- {-# INLINE gwriteBytes #-}- greadAddr _ a s- = case readCharOffAddr# a 0# s of (# s', x #) -> (# s', UChar x #)- {-# INLINE greadAddr #-}- gwriteAddr _ x a- = writeCharOffAddr# a 0# (uChar# x)- {-# INLINE gwriteAddr #-}- gbyteSize _ = SIZEOF_HSCHAR#- {-# INLINE gbyteSize #-}- gbyteAlign _ = ALIGNMENT_HSCHAR#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 0##- {-# INLINE gconTags #-}--#if SIZEOF_HSPTR == 4-#define OFFSHIFT_P 2-#else-#define OFFSHIFT_P 3-#endif--instance GPrimBytes (URec (Ptr ())) where- ggetBytes x = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSPTR# s0 of- (# s1, marr #) -> case writeAddrArray# marr 0# (uAddr# x) s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE ggetBytes #-}- gfromBytes _ off ba- = UAddr (indexAddrArray# ba (uncheckedIShiftRL# off OFFSHIFT_P#))- {-# INLINE gfromBytes #-}- greadBytes _ mba off s- = case readAddrArray# mba (uncheckedIShiftRL# off OFFSHIFT_P#) s of- (# s1, r #) -> (# s1, UAddr r #)- {-# INLINE greadBytes #-}- gwriteBytes _ mba off x- = writeAddrArray# mba (uncheckedIShiftRL# off OFFSHIFT_P#) (uAddr# x)- {-# INLINE gwriteBytes #-}- greadAddr _ a s- = case readAddrOffAddr# a 0# s of (# s', x #) -> (# s', UAddr x #)- {-# INLINE greadAddr #-}- gwriteAddr _ x a- = writeAddrOffAddr# a 0# (uAddr# x)- {-# INLINE gwriteAddr #-}- gbyteSize _ = SIZEOF_HSPTR#- {-# INLINE gbyteSize #-}- gbyteAlign _ = ALIGNMENT_HSPTR#- {-# INLINE gbyteAlign #-}- gbyteOffset _ = 0#- {-# INLINE gbyteOffset #-}- gconTags _ = 0##- {-# INLINE gconTags #-}---------------------------------------------------------------------------------------- Basic instances------------------------------------------------------------------------------------instance PrimBytes Word where- getBytes (W# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSWORD# s0 of- (# s1, marr #) -> case writeWordArray# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = W# (indexWordArray# ba (uncheckedIShiftRL# off OFFSHIFT_W#))- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off OFFSHIFT_W#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off OFFSHIFT_W#)- {-# INLINE writeBytes #-}- readAddr a s- = case readWordOffAddr# a 0# s of (# s', x #) -> (# s', W# x #)- {-# INLINE readAddr #-}- writeAddr (W# x) a- = writeWordOffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_HSWORD#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_HSWORD#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = W# (indexWordArray# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readWordArray# mba i s of (# s', x #) -> (# s', W# x #)- {-# INLINE readArray #-}- writeArray mba i (W# x) = writeWordArray# mba i x- {-# INLINE writeArray #-}---instance PrimBytes Int where- getBytes (I# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSINT# s0 of- (# s1, marr #) -> case writeIntArray# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = I# (indexIntArray# ba (uncheckedIShiftRL# off OFFSHIFT_I#))- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off OFFSHIFT_I#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off OFFSHIFT_I#)- {-# INLINE writeBytes #-}- readAddr a s- = case readIntOffAddr# a 0# s of (# s', x #) -> (# s', I# x #)- {-# INLINE readAddr #-}- writeAddr (I# x) a- = writeIntOffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_HSINT#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_HSINT#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = I# (indexIntArray# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readIntArray# mba i s of (# s', x #) -> (# s', I# x #)- {-# INLINE readArray #-}- writeArray mba i (I# x) = writeIntArray# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Float where- getBytes (F# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSFLOAT# s0 of- (# s1, marr #) -> case writeFloatArray# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = F# (indexFloatArray# ba (uncheckedIShiftRL# off OFFSHIFT_F#))- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off OFFSHIFT_F#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off OFFSHIFT_F#)- {-# INLINE writeBytes #-}- readAddr a s- = case readFloatOffAddr# a 0# s of (# s', x #) -> (# s', F# x #)- {-# INLINE readAddr #-}- writeAddr (F# x) a- = writeFloatOffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_HSFLOAT#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_HSFLOAT#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = F# (indexFloatArray# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readFloatArray# mba i s of (# s', x #) -> (# s', F# x #)- {-# INLINE readArray #-}- writeArray mba i (F# x) = writeFloatArray# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Double where- getBytes (D# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSDOUBLE# s0 of- (# s1, marr #) -> case writeDoubleArray# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = D# (indexDoubleArray# ba (uncheckedIShiftRL# off OFFSHIFT_D#))- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off OFFSHIFT_D#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off OFFSHIFT_D#)- {-# INLINE writeBytes #-}- readAddr a s- = case readDoubleOffAddr# a 0# s of (# s', x #) -> (# s', D# x #)- {-# INLINE readAddr #-}- writeAddr (D# x) a- = writeDoubleOffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_HSDOUBLE#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_HSDOUBLE#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = D# (indexDoubleArray# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readDoubleArray# mba i s of (# s', x #) -> (# s', D# x #)- {-# INLINE readArray #-}- writeArray mba i (D# x) = writeDoubleArray# mba i x- {-# INLINE writeArray #-}---instance PrimBytes (Ptr a) where- getBytes (Ptr x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_HSPTR# s0 of- (# s1, marr #) -> case writeAddrArray# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = Ptr (indexAddrArray# ba (uncheckedIShiftRL# off OFFSHIFT_P#))- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off OFFSHIFT_P#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off OFFSHIFT_P#)- {-# INLINE writeBytes #-}- readAddr a s- = case readAddrOffAddr# a 0# s of (# s', x #) -> (# s', Ptr x #)- {-# INLINE readAddr #-}- writeAddr (Ptr x) a- = writeAddrOffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_HSPTR#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_HSPTR#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = Ptr (indexAddrArray# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readAddrArray# mba i s of (# s', x #) -> (# s', Ptr x #)- {-# INLINE readArray #-}- writeArray mba i (Ptr x) = writeAddrArray# mba i x- {-# INLINE writeArray #-}---instance PrimBytes Int8 where- getBytes (I8# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_INT8# s0 of- (# s1, marr #) -> case writeInt8Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba = indexArray ba off- {-# INLINE fromBytes #-}- readBytes = readArray- {-# INLINE readBytes #-}- writeBytes = writeArray- {-# INLINE writeBytes #-}- readAddr a s- = case readInt8OffAddr# a 0# s of (# s', x #) -> (# s', I8# x #)- {-# INLINE readAddr #-}- writeAddr (I8# x) a- = writeInt8OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_INT8#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_INT8#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = I8# (indexInt8Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readInt8Array# mba i s of (# s', x #) -> (# s', I8# x #)- {-# INLINE readArray #-}- writeArray mba i (I8# x) = writeInt8Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Int16 where- getBytes (I16# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_INT16# s0 of- (# s1, marr #) -> case writeInt16Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = indexArray ba (uncheckedIShiftRL# off 1#)- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off 1#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off 1#)- {-# INLINE writeBytes #-}- readAddr a s- = case readInt16OffAddr# a 0# s of (# s', x #) -> (# s', I16# x #)- {-# INLINE readAddr #-}- writeAddr (I16# x) a- = writeInt16OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_INT16#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_INT16#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = I16# (indexInt16Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readInt16Array# mba i s of (# s', x #) -> (# s', I16# x #)- {-# INLINE readArray #-}- writeArray mba i (I16# x) = writeInt16Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Int32 where- getBytes (I32# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_INT32# s0 of- (# s1, marr #) -> case writeInt32Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = indexArray ba (uncheckedIShiftRL# off 2#)- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off 2#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off 2#)- {-# INLINE writeBytes #-}- readAddr a s- = case readInt32OffAddr# a 0# s of (# s', x #) -> (# s', I32# x #)- {-# INLINE readAddr #-}- writeAddr (I32# x) a- = writeInt32OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_INT32#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_INT32#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = I32# (indexInt32Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readInt32Array# mba i s of (# s', x #) -> (# s', I32# x #)- {-# INLINE readArray #-}- writeArray mba i (I32# x) = writeInt32Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Int64 where- getBytes (I64# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_INT64# s0 of- (# s1, marr #) -> case writeInt64Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = indexArray ba (uncheckedIShiftRL# off 3#)- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off 3#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off 3#)- {-# INLINE writeBytes #-}- readAddr a s- = case readInt64OffAddr# a 0# s of (# s', x #) -> (# s', I64# x #)- {-# INLINE readAddr #-}- writeAddr (I64# x) a- = writeInt64OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_INT64#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_INT64#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = I64# (indexInt64Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readInt64Array# mba i s of (# s', x #) -> (# s', I64# x #)- {-# INLINE readArray #-}- writeArray mba i (I64# x) = writeInt64Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Word8 where- getBytes (W8# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_WORD8# s0 of- (# s1, marr #) -> case writeWord8Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba = indexArray ba off- {-# INLINE fromBytes #-}- readBytes = readArray- {-# INLINE readBytes #-}- writeBytes = writeArray- {-# INLINE writeBytes #-}- readAddr a s- = case readWord8OffAddr# a 0# s of (# s', x #) -> (# s', W8# x #)- {-# INLINE readAddr #-}- writeAddr (W8# x) a- = writeWord8OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_WORD8#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_WORD8#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = W8# (indexWord8Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readWord8Array# mba i s of (# s', x #) -> (# s', W8# x #)- {-# INLINE readArray #-}- writeArray mba i (W8# x) = writeWord8Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Word16 where- getBytes (W16# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_WORD16# s0 of- (# s1, marr #) -> case writeWord16Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = indexArray ba (uncheckedIShiftRL# off 1#)- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off 1#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off 1#)- {-# INLINE writeBytes #-}- readAddr a s- = case readWord16OffAddr# a 0# s of (# s', x #) -> (# s', W16# x #)- {-# INLINE readAddr #-}- writeAddr (W16# x) a- = writeWord16OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_WORD16#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_WORD16#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = W16# (indexWord16Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readWord16Array# mba i s of (# s', x #) -> (# s', W16# x #)- {-# INLINE readArray #-}- writeArray mba i (W16# x) = writeWord16Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Word32 where- getBytes (W32# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_WORD32# s0 of- (# s1, marr #) -> case writeWord32Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = indexArray ba (uncheckedIShiftRL# off 2#)- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off 2#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off 2#)- {-# INLINE writeBytes #-}- readAddr a s- = case readWord32OffAddr# a 0# s of (# s', x #) -> (# s', W32# x #)- {-# INLINE readAddr #-}- writeAddr (W32# x) a- = writeWord32OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_WORD32#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_WORD32#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = W32# (indexWord32Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readWord32Array# mba i s of (# s', x #) -> (# s', W32# x #)- {-# INLINE readArray #-}- writeArray mba i (W32# x) = writeWord32Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes Word64 where- getBytes (W64# x) = case runRW#- ( \s0 -> case newByteArray# SIZEOF_WORD64# s0 of- (# s1, marr #) -> case writeWord64Array# marr 0# x s1 of- s2 -> unsafeFreezeByteArray# marr s2- ) of (# _, a #) -> a- {-# NOINLINE getBytes #-}- fromBytes off ba- = indexArray ba (uncheckedIShiftRL# off 3#)- {-# INLINE fromBytes #-}- readBytes mba off- = readArray mba (uncheckedIShiftRL# off 3#)- {-# INLINE readBytes #-}- writeBytes mba off- = writeArray mba (uncheckedIShiftRL# off 3#)- {-# INLINE writeBytes #-}- readAddr a s- = case readWord64OffAddr# a 0# s of (# s', x #) -> (# s', W64# x #)- {-# INLINE readAddr #-}- writeAddr (W64# x) a- = writeWord64OffAddr# a 0# x- {-# INLINE writeAddr #-}- byteSize _ = SIZEOF_WORD64#- {-# INLINE byteSize #-}- byteAlign _ = ALIGNMENT_WORD64#- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba i = W64# (indexWord64Array# ba i)- {-# INLINE indexArray #-}- readArray mba i s- = case readWord64Array# mba i s of (# s', x #) -> (# s', W64# x #)- {-# INLINE readArray #-}- writeArray mba i (W64# x) = writeWord64Array# mba i x- {-# INLINE writeArray #-}--instance PrimBytes (Idx x) where- getBytes = unsafeCoerce# (getBytes @Word)- {-# INLINE getBytes #-}- fromBytes = unsafeCoerce# (fromBytes @Word)- {-# INLINE fromBytes #-}- readBytes = unsafeCoerce# (readBytes @Word)- {-# INLINE readBytes #-}- writeBytes = unsafeCoerce# (writeBytes @Word)- {-# INLINE writeBytes #-}- readAddr = unsafeCoerce# (readAddr @Word)- {-# INLINE readAddr #-}- writeAddr = unsafeCoerce# (readAddr @Word)- {-# INLINE writeAddr #-}- byteSize = unsafeCoerce# (byteSize @Word)- {-# INLINE byteSize #-}- byteAlign = unsafeCoerce# (byteAlign @Word)- {-# INLINE byteAlign #-}- byteOffset = unsafeCoerce# (byteOffset @Word)- {-# INLINE byteOffset #-}- indexArray = unsafeCoerce# (indexArray @Word)- {-# INLINE indexArray #-}- readArray = unsafeCoerce# (readArray @Word)- {-# INLINE readArray #-}- writeArray = unsafeCoerce# (writeArray @Word)- {-# INLINE writeArray #-}--instance RepresentableList xs => PrimBytes (Idxs xs) where- getBytes is = case runRW#- ( \s0 -> case newByteArray# (byteSize is) s0 of- (# s1, marr #) -> unsafeFreezeByteArray# marr- (writeBytes marr 0# is s1)- ) of (# _, a #) -> a- {-# INLINE getBytes #-}- fromBytes off ba = unsafeCoerce#- (go (uncheckedIShiftRL# off OFFSHIFT_W#) (unsafeCoerce# (tList @_ @xs)))- where- go _ [] = []- go i (Proxy : ls) = W# (indexWordArray# ba i) : go (i +# 1#) ls- {-# INLINE fromBytes #-}- readBytes mba off s = unsafeCoerce#- (go (uncheckedIShiftRL# off OFFSHIFT_W#) (unsafeCoerce# (tList @_ @xs)) s)- where- go _ [] s0 = (# s0, [] #)- go i (Proxy : ls) s0 = case readWordArray# mba off s0 of- (# s1, w #) -> case go (i +# 1#) ls s1 of- (# s2, xs #) -> (# s2, W# w : xs #)- {-# INLINE readBytes #-}- writeBytes mba off is- = go (uncheckedIShiftRL# off OFFSHIFT_W#) (listIdxs is)- where- go _ [] s = s- go i (W# x :xs) s = go (i +# 1#) xs (writeWordArray# mba i x s)- {-# INLINE writeBytes #-}- readAddr addr s = unsafeCoerce#- (go addr (unsafeCoerce# (tList @_ @xs)) s)- where- go _ [] s0 = (# s0, [] #)- go i (Proxy : ls) s0 = case readWordOffAddr# i 0# s0 of- (# s1, w #) -> case go (plusAddr# i SIZEOF_HSWORD#) ls s1 of- (# s2, xs #) -> (# s2, W# w : xs #)- {-# INLINE readAddr #-}- writeAddr is addr- = go addr (listIdxs is)- where- go _ [] s = s- go i (W# x :xs) s = go (plusAddr# i SIZEOF_HSWORD#) xs- (writeWordOffAddr# i 0# x s)- {-# INLINE writeAddr #-}- byteSize _ = case dimVal (order' @xs) of- W# n -> byteSize (undefined :: Idx x) *# word2Int# n- {-# INLINE byteSize #-}- byteAlign _ = byteAlign (undefined :: Idx x)- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}- indexArray ba off- | n@(W# n#) <- dimVal (order' @xs)- = unsafeCoerce# (go (off *# word2Int# n#) n)- where- go _ 0 = []- go i n = W# (indexWordArray# ba i) : go (i +# 1#) (n-1)- {-# INLINE indexArray #-}- readArray mba off s- | n@(W# n#) <- dimVal (order' @xs)- = unsafeCoerce# (go (off *# word2Int# n#) n s)- where- go _ 0 s0 = (# s0, [] #)- go i n s0 = case readWordArray# mba off s0 of- (# s1, w #) -> case go (i +# 1#) (n-1) s1 of- (# s2, xs #) -> (# s2, W# w : xs #)- {-# INLINE readArray #-}- writeArray mba off is- | W# n# <- dimVal (order' @xs)- = go (off *# word2Int# n#) (listIdxs is)- where- go _ [] s = s- go i (W# x :xs) s = go (i +# 1#) xs (writeWordArray# mba i x s)- {-# INLINE writeArray #-}--instance ( RepresentableList xs- , L.All PrimBytes xs- ) => PrimBytes (TL.Tuple xs) where- getBytes = unsafeCoerce# (getBytes @(TS.Tuple xs))- {-# INLINE getBytes #-}- fromBytes = unsafeCoerce# (fromBytes @(TS.Tuple xs))- {-# INLINE fromBytes #-}- readBytes = unsafeCoerce# (readBytes @(TS.Tuple xs))- {-# INLINE readBytes #-}- writeBytes = unsafeCoerce# (writeBytes @(TS.Tuple xs))- {-# INLINE writeBytes #-}- readAddr = unsafeCoerce# (readAddr @(TS.Tuple xs))- {-# INLINE readAddr #-}- writeAddr = unsafeCoerce# (writeAddr @(TS.Tuple xs))- {-# INLINE writeAddr #-}- byteSize = unsafeCoerce# (byteSize @(TS.Tuple xs))- {-# INLINE byteSize #-}- byteAlign = unsafeCoerce# (byteAlign @(TS.Tuple xs))- {-# INLINE byteAlign #-}- byteOffset = unsafeCoerce# (byteOffset @(TS.Tuple xs))- {-# INLINE byteOffset #-}- indexArray = unsafeCoerce# (indexArray @(TS.Tuple xs))- {-# INLINE indexArray #-}- readArray = unsafeCoerce# (readArray @(TS.Tuple xs))- {-# INLINE readArray #-}- writeArray = unsafeCoerce# (writeArray @(TS.Tuple xs))- {-# INLINE writeArray #-}--instance ( RepresentableList xs- , L.All PrimBytes xs- ) => PrimBytes (TS.Tuple xs) where- getBytes tup = case runRW#- ( \s0 -> case newByteArray# (byteSize tup) s0 of- (# s1, marr #) -> unsafeFreezeByteArray# marr- (go marr 0# tup (types tup) s1)- ) of (# _, a #) -> a- where- go :: L.All PrimBytes ds => MutableByteArray# s- -> Int# -> TS.Tuple ds -> TypeList ds -> State# s -> State# s- go _ _ _ Empty s = s- go mb n (TS.Id x :* xs) (_ :* ts@TypeList) s- | n' <- roundUpInt# n (byteAlign x)- = go mb (n' +# byteSize x) xs ts (writeBytes mb n' x s)- {-# INLINE getBytes #-}- fromBytes off ba = go 0# (tList @_ @xs)- where- go :: L.All PrimBytes ds- => Int# -> TypeList ds -> TS.Tuple ds- go _ Empty = Empty- go n (t :* ts@TypeList)- | x <- undefP t- , n' <- roundUpInt# n (byteAlign x)- = TS.Id (fromBytes (off +# n') ba) :* go (n' +# byteSize x) ts- {-# INLINE fromBytes #-}- readBytes mb off = go mb 0# (tList @_ @xs)- where- go :: L.All PrimBytes ds- => MutableByteArray# s- -> Int# -> TypeList ds -> State# s -> (# State# s, TS.Tuple ds #)- go _ _ Empty s0 = (# s0, Empty #)- go mba n (t :* ts@TypeList) s0- | x <- undefP t- , n' <- roundUpInt# n (byteAlign x)- = case readBytes mba (off +# n') s0 of- (# s1, r #) -> case go mba (n' +# byteSize x) ts s1 of- (# s2, rs #) -> (# s2, TS.Id r :* rs #)- {-# INLINE readBytes #-}- writeBytes mba off tup = go mba 0# tup (types tup)- where- go :: L.All PrimBytes ds => MutableByteArray# s- -> Int# -> TS.Tuple ds -> TypeList ds -> State# s -> State# s- go _ _ _ Empty s = s- go mb n (TS.Id x :* xs) (_ :* ts@TypeList) s- | n' <- roundUpInt# n (byteAlign x)- = go mb (n' +# byteSize x) xs ts (writeBytes mb (off +# n') x s)- {-# INLINE writeBytes #-}- readAddr addr = go 0# (tList @_ @xs)- where- go :: L.All PrimBytes ds- => Int# -> TypeList ds -> State# s -> (# State# s, TS.Tuple ds #)- go _ Empty s0 = (# s0, Empty #)- go n (t :* ts@TypeList) s0- | x <- undefP t- , n' <- roundUpInt# n (byteAlign x)- = case readAddr (plusAddr# addr n') s0 of- (# s1, r #) -> case go (n' +# byteSize x) ts s1 of- (# s2, rs #) -> (# s2, TS.Id r :* rs #)- {-# INLINE readAddr #-}- writeAddr tup addr = go 0# tup (types tup)- where- go :: L.All PrimBytes ds- => Int# -> TS.Tuple ds -> TypeList ds -> State# s -> State# s- go _ _ Empty s = s- go n (TS.Id x :* xs) (_ :* ts@TypeList) s- | n' <- roundUpInt# n (byteAlign x)- = go (n' +# byteSize x) xs ts (writeAddr x (plusAddr# addr n') s)- {-# INLINE writeAddr #-}- byteSize _ = go 0# (tList @_ @xs)- where- go :: L.All PrimBytes ys => Int# -> TypeList ys -> Int#- go s Empty = s- go s (p :* ps) = let x = undefP p- in go (roundUpInt# s (byteAlign x) +# byteSize x) ps- {-# INLINE byteSize #-}- byteAlign _ = go (tList @_ @xs)- where- go :: L.All PrimBytes ys => TypeList ys -> Int#- go Empty = 0#- go (p :* ps) = maxInt# (byteAlign (undefP p)) (go ps)- {-# INLINE byteAlign #-}- byteOffset _ = 0#- {-# INLINE byteOffset #-}---undefP :: Proxy p -> p-undefP = const undefined-{-# INLINE undefP #-}---instance PrimBytes a => PrimBytes (Maybe a)-instance (PrimBytes a, PrimBytes b) => PrimBytes (Either a b)-instance PrimBytes a => PrimBytes [a] -- ??? likely to give inf byteSize---data PrimTag a where- PTagFloat :: PrimTag Float- PTagDouble :: PrimTag Double- PTagInt :: PrimTag Int- PTagInt8 :: PrimTag Int8- PTagInt16 :: PrimTag Int16- PTagInt32 :: PrimTag Int32- PTagInt64 :: PrimTag Int64- PTagWord :: PrimTag Word- PTagWord8 :: PrimTag Word8- PTagWord16 :: PrimTag Word16- PTagWord32 :: PrimTag Word32- PTagWord64 :: PrimTag Word64- PTagPtr :: PrimTag (Ptr a)- PTagOther :: PrimTag a--class PrimTagged a where- primTag' :: a -> PrimTag a---- | This function allows to find out a type by comparing its tag.--- This is needed for array overloading, to infer array instances.--- For non-basic types it defaults to `PTagOther`-primTag :: PrimBytes a => a -> PrimTag a-primTag = primTag'-{-# INLINE primTag #-}--instance {-# OVERLAPPABLE #-} PrimTagged a where- primTag' = const PTagOther- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Float where- primTag' = const PTagFloat- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Double where- primTag' = const PTagDouble- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Int where- primTag' = const PTagInt- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Int8 where- primTag' = const PTagInt8- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Int16 where- primTag' = const PTagInt16- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Int32 where- primTag' = const PTagInt32- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Int64 where- primTag' = const PTagInt64- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Word where- primTag' = const PTagWord- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Word8 where- primTag' = const PTagWord8- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Word16 where- primTag' = const PTagWord16- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Word32 where- primTag' = const PTagWord32- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged Word64 where- primTag' = const PTagWord64- {-# INLINE primTag' #-}--instance {-# OVERLAPPING #-} PrimTagged (Ptr a) where- primTag' = const PTagPtr- {-# INLINE primTag' #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{- |+Module : Numeric.PrimBytes+Copyright : (c) Artem Chirkin+License : BSD3++Facilities for converting Haskell data to and from raw bytes.++The main purpose of this module is to support the implementation of the @DataFrame@+`Numeric.DataFrame.Internal.Backend.Backend`. However, it also comes very useful for+writing FFI. To that end, the `PrimBytes` class is similar to+the `Foreign.Storable.Storable` class: it provides means to write+your data to and read from a raw memory area. Though, it is more flexible in that+it can work with both, foreign pointers and primitive byte arrays,+and it provides means to get data field offsets by their selector names.+On top of that, a `PrimBytes` instance can be derived via+the `GHC.Generics.Generic` machinery.++A derived `PrimBytes` instance tries to pack the data as dense as possible,+while respecting the alignment requirements. In all cases known to me,+the resulting data layout coincides with a corresponding C struct, allowing+to marshal the data without any boilerplate. However, this is not guaranteed,+but you can write a `PrimBytes` instance manually if necessary+(and report an issue plz).+++__Note about alignment, size, and padding of the data.__+There are two basic sanity assumptions about these, which are not checked+in this module at all:++ * the alignment is always a power of 2;+ * the size is always rounded up to a multiple of the alignment.++Generated instances of `PrimBytes` meet these assumptions if all components of+a data meet these assumptions too.+You are strongly advised to provide all byte offset arguments to the `PrimBytes`+functions respecting the alignment of the data;+otherwise, the data may be written or read incorrectly.+ -}+module Numeric.PrimBytes+ ( -- * PrimBytes API+ PrimBytes (..)+ , bSizeOf, bAlignOf, bFieldOffsetOf+ -- * Storable API+ --+ -- |+ -- `Foreign.Storable.Storable` can be defined in terms of `PrimBytes`+ -- by doing something like the following for your data type:+ --+ -- @+ -- instance PrimBytes a => Storable a where+ -- sizeOf = bSizeOf+ -- alignment = bAlignOf+ -- peekElemOff = bPeekElemOff+ -- pokeElemOff = bPokeElemOff+ -- peekByteOff = bPeekByteOff+ -- pokeByteOff = bPokeByteOff+ -- peek = bPeek+ -- poke = bPoke+ -- @+ , bPeekElemOff, bPokeElemOff, bPeekByteOff, bPokeByteOff, bPeek, bPoke+ -- * Specialization tools+ , PrimTag (..), primTag+ ) where++#include "MachDeps.h"++import Data.Kind (Type)+import Data.Proxy (Proxy (..))+import Data.Type.Equality ((:~:) (..))+import qualified Data.Type.List as L+import Data.Type.Lits+import GHC.Exts+import GHC.Generics+import GHC.Int+import GHC.IO (IO (..))+import GHC.Ptr (Ptr (..))+import GHC.Word+import Numeric.Dimensions+import qualified Numeric.Tuple.Lazy as TL+import qualified Numeric.Tuple.Strict as TS+import Text.Read (readMaybe)++{- |++Defines how to read and write your data to and from Haskell unboxed byte arrays+and plain pointers.++Similarly to `Foreign.Storable.Storable`, this class provides functions to get+the size and alignment of a data via phantom arguments.+Thus, the size and alignment of the data must not depend on the data content+(they depend only on the type of the data).+In particular, this means that dynamically sized structures like Haskell lists+or maps are not allowed.++This module provides default implementations for all methods of this class via+`GHC.Generics.Generic`. Hence, to make your data an instance of @PrimBytes@,+it is sufficient to write the instance head:++@+data MyData a b = ...+ deriving Generic++instance (PrimBytes a, PrimBytes b) => PrimBytes (MyData a b)+@++.. or use the @DeriveAnyClass@ extension to make it even shorter:++@+data MyData a b = ...+ deriving (Generic, PrimBytes)+@++The derived instance tries to pack the data as dense as possible, but sometimes+it is better to write the instance by hand.+If a derived type has more than one constructor, the derived instance puts+a @Word32@ tag at the beginning of the byte representation.+All fields of a constructor are packed in a C-like fashion next to each other,+while respecting their alignments.++ -}+class PrimTagged a => PrimBytes a where+ {- | List of field names.++ It is used to get field offsets using `byteFieldOffset` function.++ A Generic-derived instance has this list non-empty only if two+ obvious conditions are met:++ 1. The data has only one constructor.+ 2. The data uses record syntax to define its fields.+ -}+ type PrimFields a :: [Symbol]+ type PrimFields a = GPrimFields (Rep a)+ -- | Store content of a data type in a primitive byte array+ -- (should be used together with @byteOffset@ function).+ --+ -- Note, the default implementation of this function returns a not pinned+ -- array, which is aligned to @SIZEOF_HSWORD@.+ -- Thus, it ignores the alignment of the underlying data type if it is larger.+ -- However, alignment calculation still makes sense for data types+ -- that are smaller than @SIZEOF_HSWORD@ bytes: they are packed more densely.+ getBytes :: a -> ByteArray#+ getBytes a = case runRW#+ ( \s0 -> case newByteArray# (byteSize a) s0 of+ (# s1, marr #) -> unsafeFreezeByteArray# marr (writeBytes marr 0# a s1)+ ) of (# _, r #) -> r+ {-# NOINLINE getBytes #-}+ -- | Store content of a data type in a primitive byte array+ -- (should be used together with @byteOffset@ function).+ --+ -- In contrast to `getBytes`, this function returns a pinned byte array,+ -- aligned to the @byteAlign@ bytes of this data.+ --+ -- Note, GC guarantees not to move the created array.+ -- While this is very useful sometimes, it incurs a certain performance penalty.+ getBytesPinned :: a -> ByteArray#+ getBytesPinned a = case runRW#+ ( \s0 -> case newAlignedPinnedByteArray# (byteSize a) (byteAlign a) s0 of+ (# s1, marr #) -> unsafeFreezeByteArray# marr (writeBytes marr 0# a s1)+ ) of (# _, r #) -> r+ {-# NOINLINE getBytesPinned #-}+ -- | Load content of a data type from a primitive byte array given an offset in bytes.+ fromBytes :: Int# -- ^ Offset in bytes+ -> ByteArray# -- ^ Source array+ -> a+ -- | Read data from a mutable byte array given an offset in bytes.+ readBytes :: MutableByteArray# s -- ^ Source array+ -> Int# -- ^ Byte offset in the source array+ -> State# s -> (# State# s, a #)+ -- | Write data into a mutable byte array at a given position (offset in bytes).+ writeBytes :: MutableByteArray# s -- ^ Destination array+ -> Int# -- ^ Byte offset in the destination array+ -> a -- ^ Data to write into the array+ -> State# s -> State# s+ -- | Read data from a specified address.+ readAddr :: Addr# -> State# s -> (# State# s, a #)+ -- | Write data to a specified address.+ writeAddr :: a -> Addr# -> State# s -> State# s+ -- | Size of a data type in bytes.+ -- It should be a multiple of @byteAlign@ for indexing functions to operate+ -- correctly.+ --+ -- Implementation of this function must not inspect the argument value;+ -- a caller may provide @undefined@ in place of the argument.+ byteSize :: a -> Int#+ -- | Alignment of a data type in bytes.+ -- @byteOffset@ should be multiple of this value.+ --+ -- Implementation of this function must not inspect the argument value;+ -- a caller may provide @undefined@ in place of the argument.+ byteAlign :: a -> Int#+ -- | Offset of the data in a byte array used to store the data,+ -- measured in bytes.+ -- Should be used together with @getBytes@ function.+ -- Unless in case of special data types represented by ByteArrays,+ -- it is equal to zero.+ --+ -- Implementation of this function may inspect the argument value;+ -- a caller must not provide @undefined@ in place of the argument.+ byteOffset :: a -> Int#+ byteOffset _ = 0#+ {-# INLINE byteOffset #-}++ -- | Offset of a data record within the data type in bytes.+ --+ -- Implementation of this function must not inspect the argument value;+ -- a caller may provide @undefined@ in place of the argument.+ --+ -- The default (generic) implementation of this fucntion looks for the+ -- leftmost occurrence of a given field name (in case of multiple constructors).+ -- If a field with the given name is not found, it returns @-1@,+ -- but this is not possible thanks to @Elem name (PrimFields a)@ constraint.+ byteFieldOffset :: (Elem name (PrimFields a), KnownSymbol name)+ => Proxy# name -> a -> Int#++ -- | Index array given an element offset+ -- (which is @byteSize a@ and should be a multiple of @byteAlign a@).+ indexArray :: ByteArray# -> Int# -> a+ indexArray ba i = fromBytes (i *# byteSize @a undefined) ba+ {-# INLINE indexArray #-}++ -- | Read a mutable array given an element offset+ -- (which is @byteSize a@ and should be a multiple of @byteAlign a@).+ readArray :: MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)+ readArray ba i = readBytes ba (i *# byteSize @a undefined)+ {-# INLINE readArray #-}++ -- | Write a mutable array given an element offset+ -- (which is @byteSize a@ and should be a multiple of @byteAlign a@).+ writeArray :: MutableByteArray# s -> Int# -> a -> State# s -> State# s+ writeArray ba i = writeBytes ba (i *# byteSize @a undefined)+ {-# INLINE writeArray #-}+++ default fromBytes :: (Generic a, GPrimBytes (Rep a))+ => Int# -> ByteArray# -> a+ fromBytes i arr = to (gfromBytes proxy# 0## 0# i arr)+ {-# INLINE fromBytes #-}++ default readBytes :: (Generic a, GPrimBytes (Rep a))+ => MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)+ readBytes mba i s = case greadBytes proxy# 0## 0# mba i s of+ (# s', x #) -> (# s', to x #)+ {-# INLINE readBytes #-}++ default writeBytes :: (Generic a, GPrimBytes (Rep a))+ => MutableByteArray# s -> Int# -> a -> State# s -> State# s+ writeBytes mba i = gwriteBytes proxy# 0## 0# mba i . from+ {-# INLINE writeBytes #-}++ default readAddr :: (Generic a, GPrimBytes (Rep a))+ => Addr# -> State# s -> (# State# s, a #)+ readAddr a s = case greadAddr proxy# 0## 0# a s of+ (# s', x #) -> (# s', to x #)+ {-# INLINE readAddr #-}++ default writeAddr :: (Generic a, GPrimBytes (Rep a))+ => a -> Addr# -> State# s -> State# s+ writeAddr = gwriteAddr proxy# 0## 0# . from+ {-# INLINE writeAddr #-}++ default byteSize :: (Generic a, GPrimBytes (Rep a))+ => a -> Int#+ byteSize a = gbyteSize proxy# 0## 0# (from a) `roundUpInt` byteAlign a+ {-# INLINE byteSize #-}++ default byteAlign :: (Generic a, GPrimBytes (Rep a))+ => a -> Int#+ byteAlign a = gbyteAlign proxy# (from a)+ {-# INLINE byteAlign #-}++ default byteFieldOffset :: ( Generic a, GPrimBytes (Rep a)+ , KnownSymbol name)+ => Proxy# name -> a -> Int#+ byteFieldOffset p a = gbyteFieldOffset proxy# 0## 0# p (from a)+ {-# INLINE byteFieldOffset #-}++-- | A wrapper on `byteSize`+bSizeOf :: (PrimBytes a, Num b) => a -> b+bSizeOf a = fromIntegral (I# (byteSize a))++-- | A wrapper on `byteAlign`+bAlignOf :: (PrimBytes a, Num b) => a -> b+bAlignOf a = fromIntegral (I# (byteAlign a))++-- | A wrapper on `byteFieldOffset`.+bFieldOffsetOf :: forall (name :: Symbol) (a :: Type) (b :: Type)+ . ( PrimBytes a, Elem name (PrimFields a)+ , KnownSymbol name, Num b)+ => a -> b+bFieldOffsetOf a = fromIntegral (I# (byteFieldOffset (proxy# @Symbol @name) a))++-- | Same as `Foreign.Storable.peekElemOff`: peek an element @a@ by the offset+-- measured in @byteSize a@.+--+-- Note: the size of the element must be a multiple of its alignment for+-- a correct operation of this function.+bPeekElemOff :: forall (a :: Type) . PrimBytes a => Ptr a -> Int -> IO a+bPeekElemOff (Ptr addr) (I# i)+ = IO (readAddr (plusAddr# addr (i *# byteSize @a undefined)))++-- | Same as `Foreign.Storable.pokeElemOff`: poke an element @a@ by the offset+-- measured in @byteSize a@.+--+-- Note: the size of the element must be a multiple of its alignment for+-- a correct operation of this function.+bPokeElemOff :: forall (a :: Type) . PrimBytes a => Ptr a -> Int -> a -> IO ()+bPokeElemOff (Ptr addr) (I# i) a+ = IO (\s -> (# writeAddr a (plusAddr# addr (i *# byteSize a)) s, () #))++-- | Same as `Foreign.Storable.peekByteOff`: peek an element @a@ by the offset+-- measured in bytes.+--+-- Note: you'd better be sure the address is a multiple of+-- the data alignment (`Foreign.Storable.peek`).+bPeekByteOff :: forall (a :: Type) (b :: Type) . PrimBytes a => Ptr b -> Int -> IO a+bPeekByteOff (Ptr addr) (I# i)+ = IO (readAddr (plusAddr# addr i))++-- | Same as `Foreign.Storable.pokeByteOff`: poke an element @a@ by the offset+-- measured in bytes.+--+-- Note: you'd better be sure the address is a multiple of+-- the data alignment (`Foreign.Storable.peek`).+bPokeByteOff :: forall (a :: Type) (b :: Type) . PrimBytes a => Ptr b -> Int -> a -> IO ()+bPokeByteOff (Ptr addr) (I# i) a+ = IO (\s -> (# writeAddr a (plusAddr# addr i) s, () #))++-- | Same as `Foreign.Storable.peek`: read a data from a pointer.+--+-- Note: you'd better be sure the address is a multiple of+-- the data alignment (`Foreign.Storable.peek`).+bPeek :: forall (a :: Type) . PrimBytes a => Ptr a -> IO a+bPeek (Ptr addr) = IO (readAddr addr)++-- | Same as `Foreign.Storable.poke`: write a data to a pointer.+--+-- Note: you'd better be sure the address is a multiple of+-- the data alignment (`Foreign.Storable.peek`).+bPoke :: forall (a :: Type) . PrimBytes a => Ptr a -> a -> IO ()+bPoke (Ptr addr) a = IO (\s -> (# writeAddr a addr s, () #))++-- | Derive a list of data selectors from the data representation @Rep a@.+type family GPrimFields (rep :: Type -> Type) :: [Symbol] where+ GPrimFields (M1 D _ f) = GPrimFields f+ GPrimFields (M1 C _ f) = GPrimFields f+ GPrimFields (M1 S ('MetaSel ('Just n) _ _ _) _) = '[n]+ GPrimFields (f :*: g) = Concat (GPrimFields f) (GPrimFields g)+ GPrimFields _ = '[]++{- | Deriving `PrimBytes` using generics++This implementation relies on two assumptions, which are probably true+in the GHC implementation of derived generics and __is not checked here__:++1. @Rep a@ is a sum-of-products.+ This means the struct offset is always @4@ for the parts of the sum type,+ and a constructor tag is always at position @0@ in the struct.++2. The @Rep a@ tree is balanced.+ Thus, I can implement a simple tag encoding:+ each bit in a tag corresponds to a nesting level.+ That is, maximum possible nesting level is 31 and minimum is 0.++Therefore, the general logic for the sum type is summarized as follows:+ reserve 4 bytes for the tag and try to pack alternatives as good as possible.++If a data type has only one constructor (@Rep a@ contains no @:+:@),+then the tag is not added.+++Every function in @GPrimBytes@ has the first Proxy# argument;+it is simply used to enforce type parameter and allows easy @coerce@ implementations+for @Meta@ wrapper types.++All functions except @gbyteAlign@ have the second and third arguments:+tag mask (@Word#@) and current struct size (@Int#@);+both start with zero at the top of the @Rep a@ hierarchy.++ The tag mask is used by the sum constructors to find out where to write a bit value+ to encode left or right branch.++ The current struct size is the size (in bytes) of all elements to the left of+ the current one (before alignment).++ -}+class GPrimBytes f where+ gfromBytes :: Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> Int# -> ByteArray# -> f p+ greadBytes :: Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> MutableByteArray# s -> Int# -> State# s -> (# State# s, f p #)+ gwriteBytes :: Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> MutableByteArray# s -> Int# -> f p -> State# s -> State# s+ greadAddr :: Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> Addr# -> State# s -> (# State# s, f p #)+ gwriteAddr :: Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> f p -> Addr# -> State# s -> State# s+ -- | Cumulative size of a Rep structure+ gbyteSize :: Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> f p -> Int#+ gbyteAlign :: Proxy# p+ -> f p -> Int#+ -- | Gives an offset of the current piece of a Rep structure+ gbyteFieldOffset :: KnownSymbol name+ => Proxy# p+ -> Word# -- ^ Constructor tag position (mask)+ -> Int# -- ^ Left neighbour cumulative size (current offset before alignment)+ -> Proxy# name -> f p -> Int#+ gbyteFieldOffset _ _ _ _ _ = negateInt# 1#+ {-# INLINE gbyteFieldOffset #-}++instance GPrimBytes V1 where+ gfromBytes _ _ _ _ _ = undefined+ greadBytes _ _ _ _ _ s = (# s, undefined #)+ gwriteBytes _ _ _ _ _ _ s = s+ greadAddr _ _ _ _ s = (# s, undefined #)+ gwriteAddr _ _ _ _ _ s = s+ gbyteSize _ _ ps _ = ps+ gbyteAlign _ _ = 1#++instance GPrimBytes U1 where+ gfromBytes _ _ _ _ _ = U1+ greadBytes _ _ _ _ _ s = (# s, U1 #)+ gwriteBytes _ _ _ _ _ _ s = s+ greadAddr _ _ _ _ s = (# s, U1 #)+ gwriteAddr _ _ _ _ _ s = s+ gbyteSize _ _ ps _ = ps+ gbyteAlign _ _ = 1#++getGOff :: forall a . PrimBytes a+ => Int# -- parent cumulative size+ -> Int# -- original offset+ -> Int# -- new offset+getGOff ps i = i +# roundUpInt ps (byteAlign @a undefined)++instance PrimBytes a => GPrimBytes (K1 i a) where+ gfromBytes _ _ ps i ba = K1 (fromBytes (getGOff @a ps i) ba)+ greadBytes _ _ ps mba i = coerce (readBytes @a mba (getGOff @a ps i))+ gwriteBytes _ _ ps mba i = coerce (writeBytes @a mba (getGOff @a ps i))+ greadAddr _ _ ps addr = coerce (readAddr @a (plusAddr# addr (getGOff @a ps 0#)))+ gwriteAddr _ _ ps ka addr = writeAddr (unK1 ka) (plusAddr# addr (getGOff @a ps 0#))+ gbyteSize _ _ ps ~(K1 a) = roundUpInt ps (byteAlign a) +# byteSize a+ gbyteAlign _ = coerce (byteAlign @a)++instance {-# OVERLAPPING #-}+ (GPrimBytes f, KnownSymbol sn)+ => GPrimBytes (M1 S ('MetaSel ('Just sn) a b c) f) where+ gfromBytes p = coerce (gfromBytes @f p)+ greadBytes p = coerce (greadBytes @f p)+ gwriteBytes p = coerce (gwriteBytes @f p)+ greadAddr p = coerce (greadAddr @f p)+ gwriteAddr p = coerce (gwriteAddr @f p)+ gbyteSize p = coerce (gbyteSize @f p)+ gbyteAlign p = coerce (gbyteAlign @f p)+ gbyteFieldOffset p _ off (_ :: Proxy# n) ma+ | Just Refl <- sameSymbol (undefined :: Proxy n) (undefined :: Proxy sn)+ = off `roundUpInt` gbyteAlign p ma+ | otherwise+ = negateInt# 1#++instance GPrimBytes f => GPrimBytes (M1 i c f) where+ gfromBytes p = coerce (gfromBytes @f p)+ greadBytes p = coerce (greadBytes @f p)+ gwriteBytes p = coerce (gwriteBytes @f p)+ greadAddr p = coerce (greadAddr @f p)+ gwriteAddr p = coerce (gwriteAddr @f p)+ gbyteSize p = coerce (gbyteSize @f p)+ gbyteAlign p = coerce (gbyteAlign @f p)+ gbyteFieldOffset p = coerce (gbyteFieldOffset @f p)++instance (GPrimBytes f, GPrimBytes g) => GPrimBytes (f :*: g) where+ gfromBytes p t ps i ba = x :*: y+ where+ x = gfromBytes p t ps i ba+ y = gfromBytes p t (gbyteSize p t ps x) i ba+ greadBytes p t ps mba i s0+ | (# s1, x #) <- greadBytes p t ps mba i s0+ , (# s2, y #) <- greadBytes p t (gbyteSize p t ps x) mba i s1+ = (# s2, x :*: y #)+ gwriteBytes p t ps mba off (x :*: y) s0+ | s1 <- gwriteBytes p t ps mba off x s0+ , s2 <- gwriteBytes p t (gbyteSize p t ps x) mba off y s1+ = s2+ greadAddr p t ps addr s0+ | (# s1, x #) <- greadAddr p t ps addr s0+ , (# s2, y #) <- greadAddr p t (gbyteSize p t ps x) addr s1+ = (# s2, x :*: y #)+ gwriteAddr p t ps (x :*: y) addr s0+ | s1 <- gwriteAddr p t ps x addr s0+ , s2 <- gwriteAddr p t (gbyteSize p t ps x) y addr s1+ = s2+ gbyteSize p t ps ~(x :*: y) = gbyteSize p t (gbyteSize p t ps x) y+ gbyteAlign p ~(x :*: y) = gbyteAlign p x `maxInt` gbyteAlign p y+ gbyteFieldOffset p t ps n ~(x :*: y)+ | offX <- gbyteFieldOffset p t ps n x+ , bsX <- gbyteSize p t ps x+ , offY <- gbyteFieldOffset p t bsX n y+ = if isTrue# (offX <# 0#) then offY else offX++instance (GPrimBytes f, GPrimBytes g) => GPrimBytes (f :+: g) where+ gfromBytes p t _ off ba+ | c <- indexWord8ArrayAsWord32# ba off+ = if isTrue# (eqWord# (and# c t1) 0##)+ then L1 (gfromBytes p t1 4# off ba)+ else R1 (gfromBytes p t1 4# off ba)+ where+ t1 = upTag t+ greadBytes p t _ mba off s0+ | (# s1, c #) <- readWord8ArrayAsWord32# mba off s0+ = if isTrue# (eqWord# (and# c t1) 0##)+ then case greadBytes p t1 4# mba off s1 of+ (# s2, x #) -> (# s2, L1 x #)+ else case greadBytes p t1 4# mba off s1 of+ (# s2, y #) -> (# s2, R1 y #)+ where+ t1 = upTag t+ -- if this is the uppermost sum, overwrite the tag.+ gwriteBytes p 0## _ mba off (L1 x) s0+ | s1 <- writeWord8ArrayAsWord32# mba off 0## s0+ , s2 <- gwriteBytes p 1## 4# mba off x s1 = s2+ gwriteBytes p 0## _ mba off (R1 y) s0+ | s1 <- writeWord8ArrayAsWord32# mba off 1## s0+ , s2 <- gwriteBytes p 1## 4# mba off y s1 = s2+ -- here I know that I have written zero to the corresponding bit already+ gwriteBytes p t _ mba off (L1 x) s0+ | s1 <- gwriteBytes p (upTag t) 4# mba off x s0 = s1+ -- otherwise, carefully write a single corresponding bit+ gwriteBytes p t _ mba off (R1 y) s0+ | (# s1, c #) <- readWord8ArrayAsWord32# mba off s0+ , s2 <- writeWord8ArrayAsWord32# mba off (or# c t1) s1+ , s3 <- gwriteBytes p t1 4# mba off y s2 = s3+ where+ t1 = upTag t+ greadAddr p t _ addr s0+ | (# s1, c #) <- readWord32OffAddr# addr 0# s0+ = if isTrue# (eqWord# (and# c t1) 0##)+ then case greadAddr p t1 4# addr s1 of+ (# s2, x #) -> (# s2, L1 x #)+ else case greadAddr p t1 4# addr s1 of+ (# s2, y #) -> (# s2, R1 y #)+ where+ t1 = upTag t+ -- if this is the uppermost sum, overwrite the tag.+ gwriteAddr p 0## _ (L1 x) addr s0+ | s1 <- writeWord32OffAddr# addr 0# 0## s0+ , s2 <- gwriteAddr p 1## 4# x addr s1 = s2+ gwriteAddr p 0## _ (R1 y) addr s0+ | s1 <- writeWord32OffAddr# addr 0# 1## s0+ , s2 <- gwriteAddr p 1## 4# y addr s1 = s2+ -- here I know that I have written zero to the corresponding bit already+ gwriteAddr p t _ (L1 x) addr s0+ | s1 <- gwriteAddr p (upTag t) 4# x addr s0 = s1+ -- otherwise, carefully write a single corresponding bit+ gwriteAddr p t _ (R1 y) addr s0+ | (# s1, c #) <- readWord32OffAddr# addr 0# s0+ , s2 <- writeWord32OffAddr# addr 0# (or# c t1) s1+ , s3 <- gwriteAddr p t1 4# y addr s2 = s3+ where+ t1 = upTag t+ gbyteSize p 0## ps xy+ = maxInt+ (roundUpInt 4# (gbyteAlign p x) +# gbyteSize p 1## ps x)+ (roundUpInt 4# (gbyteAlign p y) +# gbyteSize p 1## ps y)+ where+ x = undef1 @f xy+ y = undef1 @g xy+ gbyteSize p t ps xy+ = maxInt+ (gbyteSize p (upTag t) ps (undef1 @f xy))+ (gbyteSize p (upTag t) ps (undef1 @g xy))+ gbyteAlign p xy = 4# `maxInt`+ maxInt (gbyteAlign p (undef1 @f xy))+ (gbyteAlign p (undef1 @g xy))+ -- check both branches if any of them contain the field.+ -- If there are more than one branches containing the field, the left one+ -- is preferred.+ gbyteFieldOffset p t ps n xy+ | offX <- gbyteFieldOffset p (upTag t) ps n (undef1 @f xy)+ , offY <- gbyteFieldOffset p (upTag t) ps n (undef1 @g xy)+ = if isTrue# (offX <# 0#) then offY else offX++upTag :: Word# -> Word#+upTag 0## = 1##+upTag t = uncheckedShiftL# t 1#+{-# INLINE upTag #-}+++maxInt :: Int# -> Int# -> Int#+maxInt a b = if isTrue# (a ># b) then a else b+{-# INLINE maxInt #-}++-- | Round up the first numer to a multiple of the second.+--+-- NB: this function is only used with alignment as the second number,+-- which is always a power of 2.+roundUpInt :: Int# -> Int# -> Int#+roundUpInt a b = (a +# b -# 1#) `andI#` negateInt# b+{-# INLINE roundUpInt #-}+-- It's pity that the assertion would not work due to kind of the result+-- not being Type.+-- assert (isTrue# (eqWord# (popCnt# (int2Word# b)) 1##))+--+-- The version above is optimized for second number being power of two (align)+-- The baseline implementation would be as follows:+-- roundUpInt a b = case remInt# a b of+-- 0# -> a+ -- q -> a +# b -# q++undef1 :: forall p q a . q a -> p a+undef1 = const undefined+{-# INLINE undef1 #-}++++#if SIZEOF_HSWORD == 4+#define OFFSHIFT_W 2+#else+#define OFFSHIFT_W 3+#endif++instance GPrimBytes (URec Word) where+ gfromBytes _ _ ps off ba+ = UWord (indexWord8ArrayAsWord# ba (off +# roundUpInt ps ALIGNMENT_HSWORD#))+ greadBytes _ _ ps mba off s+ = case readWord8ArrayAsWord# mba (off +# roundUpInt ps ALIGNMENT_HSWORD#) s of+ (# s1, r #) -> (# s1, UWord r #)+ gwriteBytes _ _ ps mba off x+ = writeWord8ArrayAsWord# mba (off +# roundUpInt ps ALIGNMENT_HSWORD#) (uWord# x)+ greadAddr _ _ ps a s+ = case readWordOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSWORD#)) 0# s of+ (# s', x #) -> (# s', UWord x #)+ gwriteAddr _ _ ps x a+ = writeWordOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSWORD#)) 0# (uWord# x)+ gbyteSize _ _ ps _ = roundUpInt ps ALIGNMENT_HSWORD# +# SIZEOF_HSWORD#+ gbyteAlign _ _ = ALIGNMENT_HSWORD#++#if SIZEOF_HSINT == 4+#define OFFSHIFT_I 2+#else+#define OFFSHIFT_I 3+#endif++instance GPrimBytes (URec Int) where+ gfromBytes _ _ ps off ba+ = UInt (indexWord8ArrayAsInt# ba (off +# roundUpInt ps ALIGNMENT_HSINT#))+ greadBytes _ _ ps mba off s+ = case readWord8ArrayAsInt# mba (off +# roundUpInt ps ALIGNMENT_HSINT#) s of+ (# s1, r #) -> (# s1, UInt r #)+ gwriteBytes _ _ ps mba off x+ = writeWord8ArrayAsInt# mba (off +# roundUpInt ps ALIGNMENT_HSINT#) (uInt# x)+ greadAddr _ _ ps a s+ = case readIntOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSINT#)) 0# s of+ (# s', x #) -> (# s', UInt x #)+ gwriteAddr _ _ ps x a+ = writeIntOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSINT#)) 0# (uInt# x)+ gbyteSize _ _ ps _ = roundUpInt ps ALIGNMENT_HSINT# +# SIZEOF_HSINT#+ gbyteAlign _ _ = ALIGNMENT_HSINT#++#if SIZEOF_HSFLOAT == 4+#define OFFSHIFT_F 2+#else+#define OFFSHIFT_F 3+#endif++instance GPrimBytes (URec Float) where+ gfromBytes _ _ ps off ba+ = UFloat (indexWord8ArrayAsFloat# ba (off +# roundUpInt ps ALIGNMENT_HSFLOAT#))+ greadBytes _ _ ps mba off s+ = case readWord8ArrayAsFloat# mba (off +# roundUpInt ps ALIGNMENT_HSFLOAT#) s of+ (# s1, r #) -> (# s1, UFloat r #)+ gwriteBytes _ _ ps mba off x+ = writeWord8ArrayAsFloat# mba (off +# roundUpInt ps ALIGNMENT_HSFLOAT#) (uFloat# x)+ greadAddr _ _ ps a s+ = case readFloatOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSFLOAT#)) 0# s of+ (# s', x #) -> (# s', UFloat x #)+ gwriteAddr _ _ ps x a+ = writeFloatOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSFLOAT#)) 0# (uFloat# x)+ gbyteSize _ _ ps _ = roundUpInt ps ALIGNMENT_HSFLOAT# +# SIZEOF_HSFLOAT#+ gbyteAlign _ _ = ALIGNMENT_HSFLOAT#++#if SIZEOF_HSDOUBLE == 4+#define OFFSHIFT_D 2+#else+#define OFFSHIFT_D 3+#endif++instance GPrimBytes (URec Double) where+ gfromBytes _ _ ps off ba+ = UDouble (indexWord8ArrayAsDouble# ba (off +# roundUpInt ps ALIGNMENT_HSDOUBLE#))+ greadBytes _ _ ps mba off s+ = case readWord8ArrayAsDouble# mba (off +# roundUpInt ps ALIGNMENT_HSDOUBLE#) s of+ (# s1, r #) -> (# s1, UDouble r #)+ gwriteBytes _ _ ps mba off x+ = writeWord8ArrayAsDouble# mba (off +# roundUpInt ps ALIGNMENT_HSDOUBLE#) (uDouble# x)+ greadAddr _ _ ps a s+ = case readDoubleOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSDOUBLE#)) 0# s of+ (# s', x #) -> (# s', UDouble x #)+ gwriteAddr _ _ ps x a+ = writeDoubleOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSDOUBLE#)) 0# (uDouble# x)+ gbyteSize _ _ ps _ = roundUpInt ps ALIGNMENT_HSDOUBLE# +# SIZEOF_HSDOUBLE#+ gbyteAlign _ _ = ALIGNMENT_HSDOUBLE#++-- I believe Char is always 31 bit, but checking this does not hurt+#if SIZEOF_HSCHAR == 2+#define OFFSHIFT_C 1+#elif SIZEOF_HSCHAR == 4+#define OFFSHIFT_C 2+#else+#define OFFSHIFT_C 3+#endif++instance GPrimBytes (URec Char) where+ gfromBytes _ _ ps off ba+ = UChar (indexWord8ArrayAsWideChar# ba (off +# roundUpInt ps ALIGNMENT_HSCHAR#))+ greadBytes _ _ ps mba off s+ = case readWord8ArrayAsWideChar# mba (off +# roundUpInt ps ALIGNMENT_HSCHAR#) s of+ (# s1, r #) -> (# s1, UChar r #)+ gwriteBytes _ _ ps mba off x+ = writeWord8ArrayAsWideChar# mba (off +# roundUpInt ps ALIGNMENT_HSCHAR#) (uChar# x)+ greadAddr _ _ ps a s+ = case readWideCharOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSCHAR#)) 0# s of+ (# s', x #) -> (# s', UChar x #)+ gwriteAddr _ _ ps x a+ = writeWideCharOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSCHAR#)) 0# (uChar# x)+ gbyteSize _ _ ps _ = roundUpInt ps ALIGNMENT_HSCHAR# +# SIZEOF_HSCHAR#+ gbyteAlign _ _ = ALIGNMENT_HSCHAR#++#if SIZEOF_HSPTR == 4+#define OFFSHIFT_P 2+#else+#define OFFSHIFT_P 3+#endif++instance GPrimBytes (URec (Ptr ())) where+ gfromBytes _ _ ps off ba+ = UAddr (indexWord8ArrayAsAddr# ba (off +# roundUpInt ps ALIGNMENT_HSPTR#))+ greadBytes _ _ ps mba off s+ = case readWord8ArrayAsAddr# mba (off +# roundUpInt ps ALIGNMENT_HSPTR#) s of+ (# s1, r #) -> (# s1, UAddr r #)+ gwriteBytes _ _ ps mba off x+ = writeWord8ArrayAsAddr# mba (off +# roundUpInt ps ALIGNMENT_HSPTR#) (uAddr# x)+ greadAddr _ _ ps a s+ = case readAddrOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSPTR#)) 0# s of+ (# s', x #) -> (# s', UAddr x #)+ gwriteAddr _ _ ps x a+ = writeAddrOffAddr# (plusAddr# a (roundUpInt ps ALIGNMENT_HSPTR#)) 0# (uAddr# x)+ gbyteSize _ _ ps _ = roundUpInt ps ALIGNMENT_HSPTR# +# SIZEOF_HSPTR#+ gbyteAlign _ _ = ALIGNMENT_HSPTR#+++++--------------------------------------------------------------------------------+-- Basic instances+--------------------------------------------------------------------------------+++instance PrimBytes Word where+ type PrimFields Word = '[]+ getBytes (W# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_HSWORD# s0 of+ (# s1, marr #) -> case writeWordArray# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = W# (indexWord8ArrayAsWord# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsWord# mba off s of (# s', r #) -> (# s', W# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (W# x)+ = writeWord8ArrayAsWord# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readWordOffAddr# a 0# s of (# s', x #) -> (# s', W# x #)+ {-# INLINE readAddr #-}+ writeAddr (W# x) a+ = writeWordOffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_HSWORD#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_HSWORD#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = W# (indexWordArray# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readWordArray# mba i s of (# s', x #) -> (# s', W# x #)+ {-# INLINE readArray #-}+ writeArray mba i (W# x) = writeWordArray# mba i x+ {-# INLINE writeArray #-}+++instance PrimBytes Int where+ type PrimFields Int = '[]+ getBytes (I# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_HSINT# s0 of+ (# s1, marr #) -> case writeIntArray# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = I# (indexWord8ArrayAsInt# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsInt# mba off s of (# s', r #) -> (# s', I# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (I# x)+ = writeWord8ArrayAsInt# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readIntOffAddr# a 0# s of (# s', x #) -> (# s', I# x #)+ {-# INLINE readAddr #-}+ writeAddr (I# x) a+ = writeIntOffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_HSINT#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_HSINT#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = I# (indexIntArray# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readIntArray# mba i s of (# s', x #) -> (# s', I# x #)+ {-# INLINE readArray #-}+ writeArray mba i (I# x) = writeIntArray# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Float where+ type PrimFields Float = '[]+ getBytes (F# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_HSFLOAT# s0 of+ (# s1, marr #) -> case writeFloatArray# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = F# (indexWord8ArrayAsFloat# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsFloat# mba off s of (# s', r #) -> (# s', F# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (F# x)+ = writeWord8ArrayAsFloat# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readFloatOffAddr# a 0# s of (# s', x #) -> (# s', F# x #)+ {-# INLINE readAddr #-}+ writeAddr (F# x) a+ = writeFloatOffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_HSFLOAT#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_HSFLOAT#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = F# (indexFloatArray# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readFloatArray# mba i s of (# s', x #) -> (# s', F# x #)+ {-# INLINE readArray #-}+ writeArray mba i (F# x) = writeFloatArray# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Double where+ type PrimFields Double = '[]+ getBytes (D# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_HSDOUBLE# s0 of+ (# s1, marr #) -> case writeDoubleArray# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = D# (indexWord8ArrayAsDouble# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsDouble# mba off s of (# s', r #) -> (# s', D# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (D# x)+ = writeWord8ArrayAsDouble# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readDoubleOffAddr# a 0# s of (# s', x #) -> (# s', D# x #)+ {-# INLINE readAddr #-}+ writeAddr (D# x) a+ = writeDoubleOffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_HSDOUBLE#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_HSDOUBLE#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = D# (indexDoubleArray# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readDoubleArray# mba i s of (# s', x #) -> (# s', D# x #)+ {-# INLINE readArray #-}+ writeArray mba i (D# x) = writeDoubleArray# mba i x+ {-# INLINE writeArray #-}+++instance PrimBytes (Ptr a) where+ type PrimFields (Ptr a) = '[]+ getBytes (Ptr x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_HSPTR# s0 of+ (# s1, marr #) -> case writeAddrArray# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = Ptr (indexWord8ArrayAsAddr# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsAddr# mba off s of (# s', r #) -> (# s', Ptr r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (Ptr x)+ = writeWord8ArrayAsAddr# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readAddrOffAddr# a 0# s of (# s', x #) -> (# s', Ptr x #)+ {-# INLINE readAddr #-}+ writeAddr (Ptr x) a+ = writeAddrOffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_HSPTR#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_HSPTR#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = Ptr (indexAddrArray# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readAddrArray# mba i s of (# s', x #) -> (# s', Ptr x #)+ {-# INLINE readArray #-}+ writeArray mba i (Ptr x) = writeAddrArray# mba i x+ {-# INLINE writeArray #-}+++instance PrimBytes Int8 where+ type PrimFields Int8 = '[]+ getBytes (I8# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_INT8# s0 of+ (# s1, marr #) -> case writeInt8Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba = indexArray ba off+ {-# INLINE fromBytes #-}+ readBytes = readArray+ {-# INLINE readBytes #-}+ writeBytes = writeArray+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readInt8OffAddr# a 0# s of (# s', x #) -> (# s', I8# x #)+ {-# INLINE readAddr #-}+ writeAddr (I8# x) a+ = writeInt8OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_INT8#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_INT8#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = I8# (indexInt8Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readInt8Array# mba i s of (# s', x #) -> (# s', I8# x #)+ {-# INLINE readArray #-}+ writeArray mba i (I8# x) = writeInt8Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Int16 where+ type PrimFields Int16 = '[]+ getBytes (I16# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_INT16# s0 of+ (# s1, marr #) -> case writeInt16Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = I16# (indexWord8ArrayAsInt16# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsInt16# mba off s of (# s', r #) -> (# s', I16# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (I16# x)+ = writeWord8ArrayAsInt16# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readInt16OffAddr# a 0# s of (# s', x #) -> (# s', I16# x #)+ {-# INLINE readAddr #-}+ writeAddr (I16# x) a+ = writeInt16OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_INT16#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_INT16#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = I16# (indexInt16Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readInt16Array# mba i s of (# s', x #) -> (# s', I16# x #)+ {-# INLINE readArray #-}+ writeArray mba i (I16# x) = writeInt16Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Int32 where+ type PrimFields Int32 = '[]+ getBytes (I32# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_INT32# s0 of+ (# s1, marr #) -> case writeInt32Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = I32# (indexWord8ArrayAsInt32# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsInt32# mba off s of (# s', r #) -> (# s', I32# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (I32# x)+ = writeWord8ArrayAsInt32# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readInt32OffAddr# a 0# s of (# s', x #) -> (# s', I32# x #)+ {-# INLINE readAddr #-}+ writeAddr (I32# x) a+ = writeInt32OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_INT32#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_INT32#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = I32# (indexInt32Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readInt32Array# mba i s of (# s', x #) -> (# s', I32# x #)+ {-# INLINE readArray #-}+ writeArray mba i (I32# x) = writeInt32Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Int64 where+ type PrimFields Int64 = '[]+ getBytes (I64# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_INT64# s0 of+ (# s1, marr #) -> case writeInt64Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = I64# (indexWord8ArrayAsInt64# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsInt64# mba off s of (# s', r #) -> (# s', I64# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (I64# x)+ = writeWord8ArrayAsInt64# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readInt64OffAddr# a 0# s of (# s', x #) -> (# s', I64# x #)+ {-# INLINE readAddr #-}+ writeAddr (I64# x) a+ = writeInt64OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_INT64#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_INT64#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = I64# (indexInt64Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readInt64Array# mba i s of (# s', x #) -> (# s', I64# x #)+ {-# INLINE readArray #-}+ writeArray mba i (I64# x) = writeInt64Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Word8 where+ type PrimFields Word8 = '[]+ getBytes (W8# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_WORD8# s0 of+ (# s1, marr #) -> case writeWord8Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba = indexArray ba off+ {-# INLINE fromBytes #-}+ readBytes = readArray+ {-# INLINE readBytes #-}+ writeBytes = writeArray+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readWord8OffAddr# a 0# s of (# s', x #) -> (# s', W8# x #)+ {-# INLINE readAddr #-}+ writeAddr (W8# x) a+ = writeWord8OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_WORD8#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_WORD8#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = W8# (indexWord8Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readWord8Array# mba i s of (# s', x #) -> (# s', W8# x #)+ {-# INLINE readArray #-}+ writeArray mba i (W8# x) = writeWord8Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Word16 where+ type PrimFields Word16 = '[]+ getBytes (W16# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_WORD16# s0 of+ (# s1, marr #) -> case writeWord16Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = W16# (indexWord8ArrayAsWord16# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsWord16# mba off s of (# s', r #) -> (# s', W16# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (W16# x)+ = writeWord8ArrayAsWord16# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readWord16OffAddr# a 0# s of (# s', x #) -> (# s', W16# x #)+ {-# INLINE readAddr #-}+ writeAddr (W16# x) a+ = writeWord16OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_WORD16#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_WORD16#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = W16# (indexWord16Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readWord16Array# mba i s of (# s', x #) -> (# s', W16# x #)+ {-# INLINE readArray #-}+ writeArray mba i (W16# x) = writeWord16Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Word32 where+ type PrimFields Word32 = '[]+ getBytes (W32# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_WORD32# s0 of+ (# s1, marr #) -> case writeWord32Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = W32# (indexWord8ArrayAsWord32# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsWord32# mba off s of (# s', r #) -> (# s', W32# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (W32# x)+ = writeWord8ArrayAsWord32# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readWord32OffAddr# a 0# s of (# s', x #) -> (# s', W32# x #)+ {-# INLINE readAddr #-}+ writeAddr (W32# x) a+ = writeWord32OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_WORD32#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_WORD32#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = W32# (indexWord32Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readWord32Array# mba i s of (# s', x #) -> (# s', W32# x #)+ {-# INLINE readArray #-}+ writeArray mba i (W32# x) = writeWord32Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Word64 where+ type PrimFields Word64 = '[]+ getBytes (W64# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_WORD64# s0 of+ (# s1, marr #) -> case writeWord64Array# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = W64# (indexWord8ArrayAsWord64# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsWord64# mba off s of (# s', r #) -> (# s', W64# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (W64# x)+ = writeWord8ArrayAsWord64# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readWord64OffAddr# a 0# s of (# s', x #) -> (# s', W64# x #)+ {-# INLINE readAddr #-}+ writeAddr (W64# x) a+ = writeWord64OffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_WORD64#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_WORD64#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = W64# (indexWord64Array# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readWord64Array# mba i s of (# s', x #) -> (# s', W64# x #)+ {-# INLINE readArray #-}+ writeArray mba i (W64# x) = writeWord64Array# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes Char where+ type PrimFields Char = '[]+ getBytes (C# x) = case runRW#+ ( \s0 -> case newByteArray# SIZEOF_HSCHAR# s0 of+ (# s1, marr #) -> case writeWideCharArray# marr 0# x s1 of+ s2 -> unsafeFreezeByteArray# marr s2+ ) of (# _, a #) -> a+ {-# NOINLINE getBytes #-}+ fromBytes off ba+ = C# (indexWord8ArrayAsWideChar# ba off)+ {-# INLINE fromBytes #-}+ readBytes mba off s+ = case readWord8ArrayAsWideChar# mba off s of (# s', r #) -> (# s', C# r #)+ {-# INLINE readBytes #-}+ writeBytes mba off (C# x)+ = writeWord8ArrayAsWideChar# mba off x+ {-# INLINE writeBytes #-}+ readAddr a s+ = case readWideCharOffAddr# a 0# s of (# s', x #) -> (# s', C# x #)+ {-# INLINE readAddr #-}+ writeAddr (C# x) a+ = writeWideCharOffAddr# a 0# x+ {-# INLINE writeAddr #-}+ byteSize _ = SIZEOF_HSCHAR#+ {-# INLINE byteSize #-}+ byteAlign _ = ALIGNMENT_HSCHAR#+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba i = C# (indexWideCharArray# ba i)+ {-# INLINE indexArray #-}+ readArray mba i s+ = case readWideCharArray# mba i s of (# s', x #) -> (# s', C# x #)+ {-# INLINE readArray #-}+ writeArray mba i (C# x) = writeWideCharArray# mba i x+ {-# INLINE writeArray #-}++instance PrimBytes (Idx (x :: k)) where+ type PrimFields (Idx x) = '[]+ getBytes = unsafeCoerce# (getBytes @Word)+ {-# INLINE getBytes #-}+ fromBytes = unsafeCoerce# (fromBytes @Word)+ {-# INLINE fromBytes #-}+ readBytes = unsafeCoerce# (readBytes @Word)+ {-# INLINE readBytes #-}+ writeBytes = unsafeCoerce# (writeBytes @Word)+ {-# INLINE writeBytes #-}+ readAddr = unsafeCoerce# (readAddr @Word)+ {-# INLINE readAddr #-}+ writeAddr = unsafeCoerce# (writeAddr @Word)+ {-# INLINE writeAddr #-}+ byteSize = unsafeCoerce# (byteSize @Word)+ {-# INLINE byteSize #-}+ byteAlign = unsafeCoerce# (byteAlign @Word)+ {-# INLINE byteAlign #-}+ byteFieldOffset b = unsafeCoerce# (byteFieldOffset @Word b)+ {-# INLINE byteFieldOffset #-}+ indexArray = unsafeCoerce# (indexArray @Word)+ {-# INLINE indexArray #-}+ readArray = unsafeCoerce# (readArray @Word)+ {-# INLINE readArray #-}+ writeArray = unsafeCoerce# (writeArray @Word)+ {-# INLINE writeArray #-}++anyList :: forall (k :: Type) (xs :: [k])+ . RepresentableList xs => [Any]+anyList = unsafeCoerce# (tList @_ @xs)+{-# INLINE anyList #-}++instance RepresentableList xs => PrimBytes (Idxs (xs :: [k])) where+ type PrimFields (Idxs xs) = '[]+ fromBytes off ba = unsafeCoerce# (go off (anyList @_ @xs))+ where+ go _ [] = []+ go i (_ : ls) = W# (indexWord8ArrayAsWord# ba i) : go (i +# SIZEOF_HSWORD#) ls+ {-# INLINE fromBytes #-}+ readBytes mba = unsafeCoerce# (go (anyList @_ @xs))+ where+ go [] _ s0 = (# s0, [] #)+ go (_ : ls) i s0+ | (# s1, w #) <- readWord8ArrayAsWord# mba i s0+ , (# s2, ws #) <- go ls (i +# SIZEOF_HSWORD#) s1+ = (# s2, W# w : ws #)+ {-# INLINE readBytes #-}+ writeBytes mba off = go off . listIdxs+ where+ go _ [] s = s+ go i (W# x :xs) s = go (i +# SIZEOF_HSWORD#) xs (writeWord8ArrayAsWord# mba i x s)+ {-# INLINE writeBytes #-}+ readAddr addr = unsafeCoerce# (go addr (anyList @_ @xs))+ where+ go :: forall s . Addr# -> [Any] -> State# s -> (# State# s, [Word] #)+ go _ [] s0 = (# s0, [] #)+ go i (_ : ls) s0+ | (# s1, w #) <- readWordOffAddr# i 0# s0+ , (# s2, xs #) <- go (plusAddr# i SIZEOF_HSWORD#) ls s1+ = (# s2, W# w : xs #)+ {-# INLINE readAddr #-}+ writeAddr is addr+ = go addr (listIdxs is)+ where+ go :: forall s . Addr# -> [Word] -> State# s -> State# s+ go _ [] s = s+ go i (W# x :xs) s = go (plusAddr# i SIZEOF_HSWORD#) xs+ (writeWordOffAddr# i 0# x s)+ {-# INLINE writeAddr #-}+ byteSize _ = case dimVal (order' @_ @xs) of+ W# n -> byteSize (undefined :: Idx x) *# word2Int# n+ {-# INLINE byteSize #-}+ byteAlign _ = byteAlign (undefined :: Idx x)+ {-# INLINE byteAlign #-}+ byteFieldOffset _ _ = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+ indexArray ba off+ | n@(W# n#) <- dimVal (order' @_ @xs)+ = unsafeCoerce# (go (off *# word2Int# n#) n)+ where+ go _ 0 = []+ go i n = W# (indexWordArray# ba i) : go (i +# 1#) (n-1)+ {-# INLINE indexArray #-}+ readArray mba off s+ | n@(W# n#) <- dimVal (order' @_ @xs)+ = unsafeCoerce# (go (off *# word2Int# n#) n s)+ where+ go _ 0 s0 = (# s0, [] #)+ go i n s0+ | (# s1, w #) <- readWordArray# mba i s0+ , (# s2, xs #) <- go (i +# 1#) (n-1) s1+ = (# s2, W# w : xs #)+ {-# INLINE readArray #-}+ writeArray mba off is+ | W# n# <- dimVal (order' @_ @xs)+ = go (off *# word2Int# n#) (listIdxs is)+ where+ go _ [] s = s+ go i (W# x :xs) s = go (i +# 1#) xs (writeWordArray# mba i x s)+ {-# INLINE writeArray #-}++type family TupleFields (n :: Nat) (xs :: [Type]) :: [Symbol] where+ TupleFields _ '[] = '[]+ TupleFields n (_ ': xs) = ShowNat n ': TupleFields (n + 1) xs++instance ( RepresentableList xs+ , L.All PrimBytes xs+ ) => PrimBytes (TL.Tuple xs) where+ type PrimFields (TL.Tuple xs) = TupleFields 1 xs+ getBytes = unsafeCoerce# (getBytes @(TS.Tuple xs))+ {-# INLINE getBytes #-}+ fromBytes = unsafeCoerce# (fromBytes @(TS.Tuple xs))+ {-# INLINE fromBytes #-}+ readBytes = unsafeCoerce# (readBytes @(TS.Tuple xs))+ {-# INLINE readBytes #-}+ writeBytes = unsafeCoerce# (writeBytes @(TS.Tuple xs))+ {-# INLINE writeBytes #-}+ readAddr = unsafeCoerce# (readAddr @(TS.Tuple xs))+ {-# INLINE readAddr #-}+ writeAddr = unsafeCoerce# (writeAddr @(TS.Tuple xs))+ {-# INLINE writeAddr #-}+ byteSize = unsafeCoerce# (byteSize @(TS.Tuple xs))+ {-# INLINE byteSize #-}+ byteAlign = unsafeCoerce# (byteAlign @(TS.Tuple xs))+ {-# INLINE byteAlign #-}+ byteFieldOffset p = unsafeCoerce# (byteFieldOffset @(TS.Tuple xs) p)+ {-# INLINE byteFieldOffset #-}+ indexArray = unsafeCoerce# (indexArray @(TS.Tuple xs))+ {-# INLINE indexArray #-}+ readArray = unsafeCoerce# (readArray @(TS.Tuple xs))+ {-# INLINE readArray #-}+ writeArray = unsafeCoerce# (writeArray @(TS.Tuple xs))+ {-# INLINE writeArray #-}++instance ( RepresentableList xs+ , L.All PrimBytes xs+ ) => PrimBytes (TS.Tuple xs) where+ type PrimFields (TS.Tuple xs) = TupleFields 1 xs+ fromBytes off ba = go 0# (tList @_ @xs)+ where+ go :: L.All PrimBytes ds+ => Int# -> TypeList ds -> TS.Tuple ds+ go _ Empty = Empty+ go n (t :* ts@TypeList)+ | x <- undefP t+ , n' <- roundUpInt n (byteAlign x)+ = TS.Id (fromBytes (off +# n') ba) :* go (n' +# byteSize x) ts+ {-# INLINE fromBytes #-}+ readBytes mb off = go mb 0# (tList @_ @xs)+ where+ go :: L.All PrimBytes ds+ => MutableByteArray# s+ -> Int# -> TypeList ds -> State# s -> (# State# s, TS.Tuple ds #)+ go _ _ Empty s0 = (# s0, Empty #)+ go mba n (t :* ts@TypeList) s0+ | x <- undefP t+ , n' <- roundUpInt n (byteAlign x)+ = case readBytes mba (off +# n') s0 of+ (# s1, r #) -> case go mba (n' +# byteSize x) ts s1 of+ (# s2, rs #) -> (# s2, TS.Id r :* rs #)+ {-# INLINE readBytes #-}+ writeBytes mba off tup = go mba 0# tup (types tup)+ where+ go :: L.All PrimBytes ds => MutableByteArray# s+ -> Int# -> TS.Tuple ds -> TypeList ds -> State# s -> State# s+ go _ _ _ Empty s = s+ go mb n (TS.Id x :* xs) (_ :* ts@TypeList) s+ | n' <- roundUpInt n (byteAlign x)+ = go mb (n' +# byteSize x) xs ts (writeBytes mb (off +# n') x s)+ {-# INLINE writeBytes #-}+ readAddr addr = go 0# (tList @_ @xs)+ where+ go :: L.All PrimBytes ds+ => Int# -> TypeList ds -> State# s -> (# State# s, TS.Tuple ds #)+ go _ Empty s0 = (# s0, Empty #)+ go n (t :* ts@TypeList) s0+ | x <- undefP t+ , n' <- roundUpInt n (byteAlign x)+ = case readAddr (plusAddr# addr n') s0 of+ (# s1, r #) -> case go (n' +# byteSize x) ts s1 of+ (# s2, rs #) -> (# s2, TS.Id r :* rs #)+ {-# INLINE readAddr #-}+ writeAddr tup addr = go 0# tup (types tup)+ where+ go :: L.All PrimBytes ds+ => Int# -> TS.Tuple ds -> TypeList ds -> State# s -> State# s+ go _ _ Empty s = s+ go n (TS.Id x :* xs) (_ :* ts@TypeList) s+ | n' <- roundUpInt n (byteAlign x)+ = go (n' +# byteSize x) xs ts (writeAddr x (plusAddr# addr n') s)+ {-# INLINE writeAddr #-}+ byteSize _ = go 0# 1# (tList @_ @xs)+ where+ go :: L.All PrimBytes ys => Int# -> Int# -> TypeList ys -> Int#+ go s a Empty = s `roundUpInt` a+ go s a (p :* ps) = let x = undefP p+ xa = byteAlign x+ in go ( roundUpInt s xa +# byteSize x)+ ( maxInt a xa ) ps+ {-# INLINE byteSize #-}+ byteAlign _ = go (tList @_ @xs)+ where+ go :: L.All PrimBytes ys => TypeList ys -> Int#+ go Empty = 0#+ go (p :* ps) = maxInt (byteAlign (undefP p)) (go ps)+ {-# INLINE byteAlign #-}+ byteFieldOffset name _+ | Just n <- readMaybe $ symbolVal' name+ = go (n-1) 0# (tList @_ @xs)+ | otherwise = negateInt# 1#+ where+ go :: L.All PrimBytes ys => Word -> Int# -> TypeList ys -> Int#+ go 0 s (p :* _) = s `roundUpInt` byteAlign (undefP p)+ go n s (p :* ps) = let x = undefP p+ in go (n-1) ( roundUpInt s (byteAlign x) +# byteSize x) ps+ go _ _ Empty = negateInt# 1#+ {-# INLINE byteFieldOffset #-}+++undefP :: Proxy p -> p+undefP = const undefined+{-# INLINE undefP #-}+++instance PrimBytes ()+instance PrimBytes a => PrimBytes (Maybe a)+instance ( PrimBytes a, PrimBytes b ) => PrimBytes (Either a b)+instance ( PrimBytes a, PrimBytes b )+ => PrimBytes (a, b)+instance ( PrimBytes a, PrimBytes b, PrimBytes c )+ => PrimBytes (a, b, c)+instance ( PrimBytes a, PrimBytes b, PrimBytes c, PrimBytes d )+ => PrimBytes (a, b, c, d)+instance ( PrimBytes a, PrimBytes b, PrimBytes c, PrimBytes d, PrimBytes e )+ => PrimBytes (a, b, c, d, e)+instance ( PrimBytes a, PrimBytes b, PrimBytes c, PrimBytes d, PrimBytes e+ , PrimBytes f )+ => PrimBytes (a, b, c, d, e, f)+instance ( PrimBytes a, PrimBytes b, PrimBytes c, PrimBytes d, PrimBytes e+ , PrimBytes f, PrimBytes g )+ => PrimBytes (a, b, c, d, e, f, g)+++-- | Find out which basic GHC type it is at runtime.+-- It is used for @DataFrame@ backend specialization:+-- by matching a @PrimTag a@ against its constructors, you can figure out+-- a specific implementation of @Backend a ds@+-- (e.g. whether this is a specialized float array, or a generic polymorphic array).+-- For non-basic types it defaults to `PTagOther`.+data PrimTag a where+ PTagFloat :: PrimTag Float+ PTagDouble :: PrimTag Double+ PTagInt :: PrimTag Int+ PTagInt8 :: PrimTag Int8+ PTagInt16 :: PrimTag Int16+ PTagInt32 :: PrimTag Int32+ PTagInt64 :: PrimTag Int64+ PTagWord :: PrimTag Word+ PTagWord8 :: PrimTag Word8+ PTagWord16 :: PrimTag Word16+ PTagWord32 :: PrimTag Word32+ PTagWord64 :: PrimTag Word64+ PTagChar :: PrimTag Char+ PTagPtr :: PrimTag (Ptr a)+ PTagOther :: PrimTag a++deriving instance Show (PrimTag a)+++-- | Find out which basic GHC type it is at runtime.+class PrimTagged a where+ -- | This function allows to find out a type by comparing its tag+ primTag' :: a -> PrimTag a++-- | This function allows to find out a type by comparing its tag.+-- This is needed for backend specialization, to infer array instances.+-- For non-basic types it defaults to `PTagOther`.+primTag :: PrimBytes a => a -> PrimTag a+primTag = primTag'+{-# INLINE primTag #-}++instance {-# OVERLAPPABLE #-} PrimTagged a where+ primTag' = const PTagOther+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Float where+ primTag' = const PTagFloat+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Double where+ primTag' = const PTagDouble+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Int where+ primTag' = const PTagInt+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Int8 where+ primTag' = const PTagInt8+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Int16 where+ primTag' = const PTagInt16+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Int32 where+ primTag' = const PTagInt32+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Int64 where+ primTag' = const PTagInt64+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Word where+ primTag' = const PTagWord+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Word8 where+ primTag' = const PTagWord8+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Word16 where+ primTag' = const PTagWord16+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Word32 where+ primTag' = const PTagWord32+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Word64 where+ primTag' = const PTagWord64+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged Char where+ primTag' = const PTagChar+ {-# INLINE primTag' #-}++instance {-# OVERLAPPING #-} PrimTagged (Ptr a) where+ primTag' = const PTagPtr+ {-# INLINE primTag' #-}++++#if !(MIN_VERSION_base(4,12,0))+-- these functions were introduced in base-4.12.0++writeWord8ArrayAsWideChar# :: MutableByteArray# d -> Int# -> Char# -> State# d -> State# d+writeWord8ArrayAsWideChar# mba off = writeWideCharArray# mba (uncheckedIShiftRL# off OFFSHIFT_C#)+{-# INLINE writeWord8ArrayAsWideChar# #-}++writeWord8ArrayAsAddr# :: MutableByteArray# d -> Int# -> Addr# -> State# d -> State# d+writeWord8ArrayAsAddr# mba off = writeAddrArray# mba (uncheckedIShiftRL# off OFFSHIFT_P#)+{-# INLINE writeWord8ArrayAsAddr# #-}++writeWord8ArrayAsFloat# :: MutableByteArray# d -> Int# -> Float# -> State# d -> State# d+writeWord8ArrayAsFloat# mba off = writeFloatArray# mba (uncheckedIShiftRL# off OFFSHIFT_F#)+{-# INLINE writeWord8ArrayAsFloat# #-}++writeWord8ArrayAsDouble# :: MutableByteArray# d -> Int# -> Double# -> State# d -> State# d+writeWord8ArrayAsDouble# mba off = writeDoubleArray# mba (uncheckedIShiftRL# off OFFSHIFT_D#)+{-# INLINE writeWord8ArrayAsDouble# #-}++writeWord8ArrayAsInt16# :: MutableByteArray# d -> Int# -> Int# -> State# d -> State# d+writeWord8ArrayAsInt16# mba off = writeInt16Array# mba (uncheckedIShiftRL# off 1#)+{-# INLINE writeWord8ArrayAsInt16# #-}++writeWord8ArrayAsInt32# :: MutableByteArray# d -> Int# -> Int# -> State# d -> State# d+writeWord8ArrayAsInt32# mba off = writeInt32Array# mba (uncheckedIShiftRL# off 2#)+{-# INLINE writeWord8ArrayAsInt32# #-}++writeWord8ArrayAsInt64# :: MutableByteArray# d -> Int# -> Int# -> State# d -> State# d+writeWord8ArrayAsInt64# mba off = writeInt64Array# mba (uncheckedIShiftRL# off 3#)+{-# INLINE writeWord8ArrayAsInt64# #-}++writeWord8ArrayAsInt# :: MutableByteArray# d -> Int# -> Int# -> State# d -> State# d+writeWord8ArrayAsInt# mba off = writeIntArray# mba (uncheckedIShiftRL# off OFFSHIFT_I#)+{-# INLINE writeWord8ArrayAsInt# #-}++writeWord8ArrayAsWord16# :: MutableByteArray# d -> Int# -> Word# -> State# d -> State# d+writeWord8ArrayAsWord16# mba off = writeWord16Array# mba (uncheckedIShiftRL# off 1#)+{-# INLINE writeWord8ArrayAsWord16# #-}++writeWord8ArrayAsWord32# :: MutableByteArray# d -> Int# -> Word# -> State# d -> State# d+writeWord8ArrayAsWord32# mba off = writeWord32Array# mba (uncheckedIShiftRL# off 2#)+{-# INLINE writeWord8ArrayAsWord32# #-}++writeWord8ArrayAsWord64# :: MutableByteArray# d -> Int# -> Word# -> State# d -> State# d+writeWord8ArrayAsWord64# mba off = writeWord64Array# mba (uncheckedIShiftRL# off 3#)+{-# INLINE writeWord8ArrayAsWord64# #-}++writeWord8ArrayAsWord# :: MutableByteArray# d -> Int# -> Word# -> State# d -> State# d+writeWord8ArrayAsWord# mba off = writeWordArray# mba (uncheckedIShiftRL# off OFFSHIFT_W#)+{-# INLINE writeWord8ArrayAsWord# #-}++readWord8ArrayAsWideChar# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Char# #)+readWord8ArrayAsWideChar# mba off = readWideCharArray# mba (uncheckedIShiftRL# off OFFSHIFT_C#)+{-# INLINE readWord8ArrayAsWideChar# #-}++readWord8ArrayAsAddr# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Addr# #)+readWord8ArrayAsAddr# mba off = readAddrArray# mba (uncheckedIShiftRL# off OFFSHIFT_P#)+{-# INLINE readWord8ArrayAsAddr# #-}++readWord8ArrayAsFloat# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Float# #)+readWord8ArrayAsFloat# mba off = readFloatArray# mba (uncheckedIShiftRL# off OFFSHIFT_F#)+{-# INLINE readWord8ArrayAsFloat# #-}++readWord8ArrayAsDouble# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Double# #)+readWord8ArrayAsDouble# mba off = readDoubleArray# mba (uncheckedIShiftRL# off OFFSHIFT_D#)+{-# INLINE readWord8ArrayAsDouble# #-}++readWord8ArrayAsInt16# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)+readWord8ArrayAsInt16# mba off = readInt16Array# mba (uncheckedIShiftRL# off 1#)+{-# INLINE readWord8ArrayAsInt16# #-}++readWord8ArrayAsInt32# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)+readWord8ArrayAsInt32# mba off = readInt32Array# mba (uncheckedIShiftRL# off 2#)+{-# INLINE readWord8ArrayAsInt32# #-}++readWord8ArrayAsInt64# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)+readWord8ArrayAsInt64# mba off = readInt64Array# mba (uncheckedIShiftRL# off 3#)+{-# INLINE readWord8ArrayAsInt64# #-}++readWord8ArrayAsInt# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)+readWord8ArrayAsInt# mba off = readIntArray# mba (uncheckedIShiftRL# off OFFSHIFT_I#)+{-# INLINE readWord8ArrayAsInt# #-}++readWord8ArrayAsWord16# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)+readWord8ArrayAsWord16# mba off = readWord16Array# mba (uncheckedIShiftRL# off 1#)+{-# INLINE readWord8ArrayAsWord16# #-}++readWord8ArrayAsWord32# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)+readWord8ArrayAsWord32# mba off = readWord32Array# mba (uncheckedIShiftRL# off 2#)+{-# INLINE readWord8ArrayAsWord32# #-}++readWord8ArrayAsWord64# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)+readWord8ArrayAsWord64# mba off = readWord64Array# mba (uncheckedIShiftRL# off 3#)+{-# INLINE readWord8ArrayAsWord64# #-}++readWord8ArrayAsWord# :: MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)+readWord8ArrayAsWord# mba off = readWordArray# mba (uncheckedIShiftRL# off OFFSHIFT_W#)+{-# INLINE readWord8ArrayAsWord# #-}++indexWord8ArrayAsWideChar# :: ByteArray# -> Int# -> Char#+indexWord8ArrayAsWideChar# ba off = indexWideCharArray# ba (uncheckedIShiftRL# off OFFSHIFT_C#)+{-# INLINE indexWord8ArrayAsWideChar# #-}++indexWord8ArrayAsAddr# :: ByteArray# -> Int# -> Addr#+indexWord8ArrayAsAddr# ba off = indexAddrArray# ba (uncheckedIShiftRL# off OFFSHIFT_P#)+{-# INLINE indexWord8ArrayAsAddr# #-}++indexWord8ArrayAsFloat# :: ByteArray# -> Int# -> Float#+indexWord8ArrayAsFloat# ba off = indexFloatArray# ba (uncheckedIShiftRL# off OFFSHIFT_F#)+{-# INLINE indexWord8ArrayAsFloat# #-}++indexWord8ArrayAsDouble# :: ByteArray# -> Int# -> Double#+indexWord8ArrayAsDouble# ba off = indexDoubleArray# ba (uncheckedIShiftRL# off OFFSHIFT_D#)+{-# INLINE indexWord8ArrayAsDouble# #-}++indexWord8ArrayAsInt16# :: ByteArray# -> Int# -> Int#+indexWord8ArrayAsInt16# ba off = indexInt16Array# ba (uncheckedIShiftRL# off 1#)+{-# INLINE indexWord8ArrayAsInt16# #-}++indexWord8ArrayAsInt32# :: ByteArray# -> Int# -> Int#+indexWord8ArrayAsInt32# ba off = indexInt32Array# ba (uncheckedIShiftRL# off 2#)+{-# INLINE indexWord8ArrayAsInt32# #-}++indexWord8ArrayAsInt64# :: ByteArray# -> Int# -> Int#+indexWord8ArrayAsInt64# ba off = indexInt64Array# ba (uncheckedIShiftRL# off 3#)+{-# INLINE indexWord8ArrayAsInt64# #-}++indexWord8ArrayAsInt# :: ByteArray# -> Int# -> Int#+indexWord8ArrayAsInt# ba off = indexIntArray# ba (uncheckedIShiftRL# off OFFSHIFT_I#)+{-# INLINE indexWord8ArrayAsInt# #-}++indexWord8ArrayAsWord16# :: ByteArray# -> Int# -> Word#+indexWord8ArrayAsWord16# ba off = indexWord16Array# ba (uncheckedIShiftRL# off 1#)+{-# INLINE indexWord8ArrayAsWord16# #-}++indexWord8ArrayAsWord32# :: ByteArray# -> Int# -> Word#+indexWord8ArrayAsWord32# ba off = indexWord32Array# ba (uncheckedIShiftRL# off 2#)+{-# INLINE indexWord8ArrayAsWord32# #-}++indexWord8ArrayAsWord64# :: ByteArray# -> Int# -> Word#+indexWord8ArrayAsWord64# ba off = indexWord64Array# ba (uncheckedIShiftRL# off 3#)+{-# INLINE indexWord8ArrayAsWord64# #-}++indexWord8ArrayAsWord# :: ByteArray# -> Int# -> Word#+indexWord8ArrayAsWord# ba off = indexWordArray# ba (uncheckedIShiftRL# off OFFSHIFT_W#)+{-# INLINE indexWord8ArrayAsWord# #-}++#endif
+ src/Numeric/ProductOrd.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Numeric.ProductOrd+-- Copyright : (c) Artem Chirkin+-- License : BSD3+--+--+-- Compare product types -- partial order.+--+-----------------------------------------------------------------------------+module Numeric.ProductOrd (ProductOrder (..), PartialOrdering (..), fromOrdering) where+++import Data.Data+import Data.Kind (Type)+import Data.Monoid as Mon (Monoid (..))+import Data.Semigroup as Sem (Semigroup (..), stimesIdempotentMonoid)+import GHC.Generics++import Numeric.TypedList++-- | Partial order for comparing product types --+-- [product order](https://en.wikipedia.org/wiki/Product_order).+class ProductOrder a where+ -- | Same as `compare`, but may return @Incomparable@.+ cmp :: a -> a -> PartialOrdering++-- | Similar to `Ordering`, but may be @Incomparable@.+data PartialOrdering = PLT | PEQ | PGT | Incomparable+ deriving ( Eq, Ord, Show, Read, Data, Typeable, Generic, Enum, Bounded )++-- | Extend `Ordering` with @Incomparable@ option.+fromOrdering :: Ordering -> PartialOrdering+fromOrdering LT = PLT+fromOrdering EQ = PEQ+fromOrdering GT = PGT+{-# INLINE fromOrdering #-}++instance Sem.Semigroup PartialOrdering where+ Incomparable <> _ = Incomparable+ _ <> Incomparable = Incomparable+ PLT <> PGT = Incomparable+ PGT <> PLT = Incomparable+ PLT <> _ = PLT+ PGT <> _ = PGT+ PEQ <> y = y++ stimes = stimesIdempotentMonoid++instance Mon.Monoid PartialOrdering where+ mempty = PEQ+#if !(MIN_VERSION_base(4,11,0))+ mappend = (<>)+#endif++instance All Ord (Map f xs)+ => ProductOrder (TypedList (f :: k -> Type) (xs :: [k])) where+ cmp U U = PEQ+ cmp (a :* as) (b :* bs) = fromOrdering (compare a b) <> cmp as bs+++cmp' :: Ord a => a -> a -> PartialOrdering+cmp' a b = fromOrdering (compare a b)+{-# INLINE cmp' #-}++instance (Ord a1, Ord a2)+ => ProductOrder (a1, a2) where+ cmp (a1, a2)+ (b1, b2)+ = cmp' a1 b1 <> cmp' a2 b2++instance (Ord a1, Ord a2, Ord a3)+ => ProductOrder (a1, a2, a3) where+ cmp (a1, a2, a3)+ (b1, b2, b3)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3++instance (Ord a1, Ord a2, Ord a3, Ord a4)+ => ProductOrder (a1, a2, a3, a4) where+ cmp (a1, a2, a3, a4)+ (b1, b2, b3, b4)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ <> cmp' a4 b4++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5)+ => ProductOrder (a1, a2, a3, a4, a5) where+ cmp (a1, a2, a3, a4, a5)+ (b1, b2, b3, b4, b5)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ <> cmp' a4 b4 <> cmp' a5 b5++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6)+ => ProductOrder (a1, a2, a3, a4, a5, a6) where+ cmp (a1, a2, a3, a4, a5, a6)+ (b1, b2, b3, b4, b5, b6)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ <> cmp' a4 b4 <> cmp' a5 b5 <> cmp' a6 b6++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7)+ => ProductOrder (a1, a2, a3, a4, a5, a6, a7) where+ cmp (a1, a2, a3, a4, a5, a6, a7)+ (b1, b2, b3, b4, b5, b6, b7)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ <> cmp' a4 b4 <> cmp' a5 b5 <> cmp' a6 b6+ <> cmp' a7 b7++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7, Ord a8)+ => ProductOrder (a1, a2, a3, a4, a5, a6, a7, a8) where+ cmp (a1, a2, a3, a4, a5, a6, a7, a8)+ (b1, b2, b3, b4, b5, b6, b7, b8)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ <> cmp' a4 b4 <> cmp' a5 b5 <> cmp' a6 b6+ <> cmp' a7 b7 <> cmp' a8 b8++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7, Ord a8, Ord a9)+ => ProductOrder (a1, a2, a3, a4, a5, a6, a7, a8, a9) where+ cmp (a1, a2, a3, a4, a5, a6, a7, a8, a9)+ (b1, b2, b3, b4, b5, b6, b7, b8, b9)+ = cmp' a1 b1 <> cmp' a2 b2 <> cmp' a3 b3+ <> cmp' a4 b4 <> cmp' a5 b5 <> cmp' a6 b6+ <> cmp' a7 b7 <> cmp' a8 b8 <> cmp' a9 b9
+ src/Numeric/ProductOrd/NonTransitive.hs view
@@ -0,0 +1,315 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Numeric.ProductOrd.NonTransitive+-- Copyright : (c) Artem Chirkin+-- License : BSD3+--+--+-- Compare product types using non-transitive `Ord` instances:+--+-- * \( a = b \) and \( b = c \) __does not mean__ \( a = c \);+-- * but, if nor \( a > b \) neither \( b > a \), then \( a = b \).+--+-- To remind yourself that `ProductOrd` is not fully faithful, you may+-- import it qualified, e.g.+--+-- > import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+--+-----------------------------------------------------------------------------+module Numeric.ProductOrd.NonTransitive (ProductOrd (..), toOrdering) where++import Control.Monad.Fix+import Control.Monad.Zip+import Data.Bits (Bits, FiniteBits)+import Data.Coerce+import Data.Data+import Data.Foldable+import Data.Kind (Type)+import Data.Monoid as Mon (Monoid (..))+import Data.Semigroup as Sem (Semigroup (..))+import Foreign.Storable (Storable)+import GHC.Generics++import Numeric.ProductOrd+import Numeric.TypedList++{-|+ Redefine `Ord` instance for a type which is a cartesian product --+ as a partial __[product order](https://en.wikipedia.org/wiki/Product_order)__.++ Since vanilla Haskell `Ord` class is always about total order, @ProductOrd@+ instance is not particularly correct.+ However, it turns out to be very useful for comparing vector or tuple-like types.++ The implementation of `ProductOrd` in this module+ workarounds this by using a __non-transitive `Eq` instance__:+ \[+ a = b \iff \neg (a > b) \land \neg (b > a)+ \]++ Another inconsistency with the Haskell Report is the `min` and `max` functions;+ these are simply element-wise minimum and maximum here.+ Thus, these instances preserve important properties like+ @min a b <= a && min a b <= b@, but do not preserve+ a property that @min a b == a || min a b == b@.++ All of this is really useful in geometry applications and for calculating things+ like [Pareto dominance](https://en.wikipedia.org/wiki/Pareto_efficiency),+ but should be used with care.+ Remember about this if you want to put a @ProductOrd@ into a @Set@ or a @Map@!+ -}+newtype ProductOrd a = ProductOrd { getProductOrd :: a }+ deriving ( Show, Read, Data, Typeable, Generic, Generic1+ , Num, Enum, Bounded, Floating, Fractional+ , Semigroup, Monoid, Storable, Traversable)++deriving instance (Ord (ProductOrd a), Integral a) => Integral (ProductOrd a)+deriving instance (Ord (ProductOrd a), Bits a) => Bits (ProductOrd a)+deriving instance (Ord (ProductOrd a), FiniteBits a) => FiniteBits (ProductOrd a)+deriving instance (Ord (ProductOrd a), Real a) => Real (ProductOrd a)+deriving instance (Ord (ProductOrd a), RealFrac a) => RealFrac (ProductOrd a)+deriving instance (Ord (ProductOrd a), RealFloat a) => RealFloat (ProductOrd a)++instance Foldable ProductOrd where+ foldMap = coerce+ elem = k (==)+ where+ k :: (a -> a -> Bool) -> a -> ProductOrd a -> Bool+ k = coerce+ foldl = coerce+ foldl' = coerce+ foldl1 _ = coerce+ foldr f z (ProductOrd x) = f x z+ foldr' = foldr+ foldr1 _ = coerce+ length _ = 1+ maximum = coerce+ minimum = coerce+ null _ = False+ product = coerce+ sum = coerce+ toList (ProductOrd x) = [x]++instance Functor ProductOrd where+ fmap = coerce++instance Applicative ProductOrd where+ pure = ProductOrd+ (<*>) = coerce++instance Monad ProductOrd where+ m >>= k = k (getProductOrd m)++instance MonadFix ProductOrd where+ mfix f = ProductOrd (fix (getProductOrd . f))++instance MonadZip ProductOrd where+ mzipWith = coerce+ munzip = coerce++{-# ANN module "HLint: ignore Redundant compare" #-}+instance Ord (ProductOrd a) => Eq (ProductOrd a) where+ a == b = compare a b == EQ+ {-# INLINE (==) #-}++instance All Ord (Map f xs)+ => Ord (ProductOrd (TypedList (f :: k -> Type) (xs :: [k]))) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd U >= ProductOrd U = True+ ProductOrd (a :* as) >= ProductOrd (b :* bs)+ = a >= b && ProductOrd as >= ProductOrd bs+ ProductOrd U <= ProductOrd U = True+ ProductOrd (a :* as) <= ProductOrd (b :* bs)+ = a <= b && ProductOrd as <= ProductOrd bs+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ min (ProductOrd U) (ProductOrd U) = ProductOrd U+ min (ProductOrd (a :* as)) (ProductOrd (b :* bs))+ = ProductOrd (min a b :* getProductOrd (min (ProductOrd as) (ProductOrd bs)))+ max (ProductOrd U) (ProductOrd U) = ProductOrd U+ max (ProductOrd (a :* as)) (ProductOrd (b :* bs))+ = ProductOrd (max a b :* getProductOrd (max (ProductOrd as) (ProductOrd bs)))++instance (Ord a1, Ord a2) => Ord (ProductOrd (a1, a2)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2) >= ProductOrd (b1, b2)+ = a1 >= b1 && a2 >= b2+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2) <= ProductOrd (b1, b2)+ = a1 <= b1 && a2 <= b2+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2)) (ProductOrd (b1, b2))+ = ProductOrd (min a1 b1, min a2 b2)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2)) (ProductOrd (b1, b2))+ = ProductOrd (max a1 b1, max a2 b2)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3) => Ord (ProductOrd (a1, a2, a3)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3) >= ProductOrd (b1, b2, b3)+ = a1 >= b1 && a2 >= b2 && a3 >= b3+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3) <= ProductOrd (b1, b2, b3)+ = a1 <= b1 && a2 <= b2 && a3 <= b3+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3)) (ProductOrd (b1, b2, b3))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3)) (ProductOrd (b1, b2, b3))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4)+ => Ord (ProductOrd (a1, a2, a3, a4)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4) >= ProductOrd (b1, b2, b3, b4)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4) <= ProductOrd (b1, b2, b3, b4)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4)) (ProductOrd (b1, b2, b3, b4))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4)) (ProductOrd (b1, b2, b3, b4))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5)+ => Ord (ProductOrd (a1, a2, a3, a4, a5)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5) >= ProductOrd (b1, b2, b3, b4, b5)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5) <= ProductOrd (b1, b2, b3, b4, b5)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5)) (ProductOrd (b1, b2, b3, b4, b5))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5)) (ProductOrd (b1, b2, b3, b4, b5))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6) >= ProductOrd (b1, b2, b3, b4, b5, b6)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6) <= ProductOrd (b1, b2, b3, b4, b5, b6)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6)) (ProductOrd (b1, b2, b3, b4, b5, b6))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6)) (ProductOrd (b1, b2, b3, b4, b5, b6))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6, a7)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7) >= ProductOrd (b1, b2, b3, b4, b5, b6, b7)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6 && a7 >= b7+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7) <= ProductOrd (b1, b2, b3, b4, b5, b6, b7)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6 && a7 <= b7+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6, a7)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6, min a7 b7)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6, a7)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6, max a7 b7)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7, Ord a8)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8) >= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6 && a7 >= b7 && a8 >= b8+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8) <= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6 && a7 <= b7 && a8 <= b8+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6, min a7 b7, min a8 b8)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6, max a7 b7, max a8 b8)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7, Ord a8, Ord a9)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9) >= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6 && a7 >= b7 && a8 >= b8 && a9 >= b9+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9) <= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6 && a7 <= b7 && a8 <= b8 && a9 <= b9+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6, min a7 b7, min a8 b8, min a9 b9)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6, max a7 b7, max a8 b8, max a9 b9)+ {-# INLINE max #-}++-- | Treat `Incomparable` as EQ (non-transitive equality).+toOrdering :: PartialOrdering -> Ordering+toOrdering PLT = LT+toOrdering PGT = GT+toOrdering _ = EQ
+ src/Numeric/ProductOrd/Partial.hs view
@@ -0,0 +1,318 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Numeric.ProductOrd.Partial+-- Copyright : (c) Artem Chirkin+-- License : BSD3+--+--+-- Compare product types using partial `Ord` instances:+--+-- * if nor \( a > b \), nor \( b > a \), neither, \( a = b \),+-- then @compare a b == undefined@+--+-- To remind yourself that `ProductOrd` is partial, you may+-- import it qualified, e.g.+--+-- > import qualified Numeric.ProductOrd.Partial as Partial+--+-----------------------------------------------------------------------------+module Numeric.ProductOrd.Partial (ProductOrd (..), toOrdering) where++import Control.Monad.Fix+import Control.Monad.Zip+import Data.Bits (Bits, FiniteBits)+import Data.Coerce+import Data.Data+import Data.Foldable+import Data.Kind (Type)+import Data.Monoid as Mon (Monoid (..))+import Data.Semigroup as Sem (Semigroup (..))+import Foreign.Storable (Storable)+import GHC.Generics++import Numeric.ProductOrd+import Numeric.TypedList++{-|+ Redefine `Ord` instance for a type which is a cartesian product --+ as a partial __[product order](https://en.wikipedia.org/wiki/Product_order)__.++ Since vanilla Haskell `Ord` class is always about total order, @ProductOrd@+ instance is not particularly correct.+ However, it turns out to be very useful for comparing vector or tuple-like types.++ The implementation of `ProductOrd` in this module+ workarounds this by using a __partial @compare@ function in an `Eq` instance__:+ \[+ \neg (a > b) \land \neg (b > a) \land \neg (a = b)+ \Rightarrow \mathtt{compare\ a\ b == undefined}+ \]++ Another inconsistency with the Haskell Report is the `min` and `max` functions;+ these are simply element-wise minimum and maximum here.+ Thus, these instances preserve important properties like+ @min a b <= a && min a b <= b@, but do not preserve+ a property that @min a b == a || min a b == b@.++ All of this is really useful in geometry applications and for calculating things+ like [Pareto dominance](https://en.wikipedia.org/wiki/Pareto_efficiency),+ but should be used with care.+ In particular, never use @ProductOrd@ as a key to a @Set@ or a @Map@!+ -}+newtype ProductOrd a = ProductOrd { getProductOrd :: a }+ deriving ( Eq, Show, Read, Data, Typeable, Generic, Generic1+ , Num, Enum, Bounded, Floating, Fractional+ , Semigroup, Monoid, Storable, Traversable+ , Bits, FiniteBits)++deriving instance (Ord (ProductOrd a), Integral a) => Integral (ProductOrd a)+deriving instance (Ord (ProductOrd a), Real a) => Real (ProductOrd a)+deriving instance (Ord (ProductOrd a), RealFrac a) => RealFrac (ProductOrd a)+deriving instance (Ord (ProductOrd a), RealFloat a) => RealFloat (ProductOrd a)++instance Foldable ProductOrd where+ foldMap = coerce+ elem = k (==)+ where+ k :: (a -> a -> Bool) -> a -> ProductOrd a -> Bool+ k = coerce+ foldl = coerce+ foldl' = coerce+ foldl1 _ = coerce+ foldr f z (ProductOrd x) = f x z+ foldr' = foldr+ foldr1 _ = coerce+ length _ = 1+ maximum = coerce+ minimum = coerce+ null _ = False+ product = coerce+ sum = coerce+ toList (ProductOrd x) = [x]++instance Functor ProductOrd where+ fmap = coerce++instance Applicative ProductOrd where+ pure = ProductOrd+ (<*>) = coerce++instance Monad ProductOrd where+ m >>= k = k (getProductOrd m)++instance MonadFix ProductOrd where+ mfix f = ProductOrd (fix (getProductOrd . f))++instance MonadZip ProductOrd where+ mzipWith = coerce+ munzip = coerce++instance {-# INCOHERENT #-}+ All Ord (Map f xs)+ => Eq (ProductOrd (TypedList (f :: k -> Type) (xs :: [k]))) where+ ProductOrd U == ProductOrd U = True+ ProductOrd (a :* as) == ProductOrd (b :* bs)+ = a == b && ProductOrd as == ProductOrd bs++instance All Ord (Map f xs)+ => Ord (ProductOrd (TypedList (f :: k -> Type) (xs :: [k]))) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd U >= ProductOrd U = True+ ProductOrd (a :* as) >= ProductOrd (b :* bs)+ = a >= b && ProductOrd as >= ProductOrd bs+ ProductOrd U <= ProductOrd U = True+ ProductOrd (a :* as) <= ProductOrd (b :* bs)+ = a <= b && ProductOrd as <= ProductOrd bs+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ min (ProductOrd U) (ProductOrd U) = ProductOrd U+ min (ProductOrd (a :* as)) (ProductOrd (b :* bs))+ = ProductOrd (min a b :* getProductOrd (min (ProductOrd as) (ProductOrd bs)))+ max (ProductOrd U) (ProductOrd U) = ProductOrd U+ max (ProductOrd (a :* as)) (ProductOrd (b :* bs))+ = ProductOrd (max a b :* getProductOrd (max (ProductOrd as) (ProductOrd bs)))++instance (Ord a1, Ord a2) => Ord (ProductOrd (a1, a2)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2) >= ProductOrd (b1, b2)+ = a1 >= b1 && a2 >= b2+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2) <= ProductOrd (b1, b2)+ = a1 <= b1 && a2 <= b2+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2)) (ProductOrd (b1, b2))+ = ProductOrd (min a1 b1, min a2 b2)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2)) (ProductOrd (b1, b2))+ = ProductOrd (max a1 b1, max a2 b2)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3) => Ord (ProductOrd (a1, a2, a3)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3) >= ProductOrd (b1, b2, b3)+ = a1 >= b1 && a2 >= b2 && a3 >= b3+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3) <= ProductOrd (b1, b2, b3)+ = a1 <= b1 && a2 <= b2 && a3 <= b3+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3)) (ProductOrd (b1, b2, b3))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3)) (ProductOrd (b1, b2, b3))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4)+ => Ord (ProductOrd (a1, a2, a3, a4)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4) >= ProductOrd (b1, b2, b3, b4)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4) <= ProductOrd (b1, b2, b3, b4)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4)) (ProductOrd (b1, b2, b3, b4))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4)) (ProductOrd (b1, b2, b3, b4))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5)+ => Ord (ProductOrd (a1, a2, a3, a4, a5)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5) >= ProductOrd (b1, b2, b3, b4, b5)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5) <= ProductOrd (b1, b2, b3, b4, b5)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5)) (ProductOrd (b1, b2, b3, b4, b5))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5)) (ProductOrd (b1, b2, b3, b4, b5))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6) >= ProductOrd (b1, b2, b3, b4, b5, b6)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6) <= ProductOrd (b1, b2, b3, b4, b5, b6)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6)) (ProductOrd (b1, b2, b3, b4, b5, b6))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6)) (ProductOrd (b1, b2, b3, b4, b5, b6))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6, a7)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7) >= ProductOrd (b1, b2, b3, b4, b5, b6, b7)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6 && a7 >= b7+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7) <= ProductOrd (b1, b2, b3, b4, b5, b6, b7)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6 && a7 <= b7+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6, a7)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6, min a7 b7)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6, a7)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6, max a7 b7)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7, Ord a8)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8) >= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6 && a7 >= b7 && a8 >= b8+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8) <= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6 && a7 <= b7 && a8 <= b8+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6, min a7 b7, min a8 b8)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6, max a7 b7, max a8 b8)+ {-# INLINE max #-}++instance (Ord a1, Ord a2, Ord a3, Ord a4, Ord a5, Ord a6, Ord a7, Ord a8, Ord a9)+ => Ord (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9)) where+ ProductOrd x > ProductOrd y = cmp x y == PGT+ {-# INLINE (>) #-}+ ProductOrd x < ProductOrd y = cmp x y == PLT+ {-# INLINE (<) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9) >= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9)+ = a1 >= b1 && a2 >= b2 && a3 >= b3 && a4 >= b4 && a5 >= b5 && a6 >= b6 && a7 >= b7 && a8 >= b8 && a9 >= b9+ {-# INLINE (>=) #-}+ ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9) <= ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9)+ = a1 <= b1 && a2 <= b2 && a3 <= b3 && a4 <= b4 && a5 <= b5 && a6 <= b6 && a7 <= b7 && a8 <= b8 && a9 <= b9+ {-# INLINE (<=) #-}+ compare (ProductOrd a) (ProductOrd b) = toOrdering $ cmp a b+ {-# INLINE compare #-}+ min (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9))+ = ProductOrd (min a1 b1, min a2 b2, min a3 b3, min a4 b4, min a5 b5, min a6 b6, min a7 b7, min a8 b8, min a9 b9)+ {-# INLINE min #-}+ max (ProductOrd (a1, a2, a3, a4, a5, a6, a7, a8, a9)) (ProductOrd (b1, b2, b3, b4, b5, b6, b7, b8, b9))+ = ProductOrd (max a1 b1, max a2 b2, max a3 b3, max a4 b4, max a5 b5, max a6 b6, max a7 b7, max a8 b8, max a9 b9)+ {-# INLINE max #-}++-- | Treat `Incomparable` as error (partial function).+toOrdering :: PartialOrdering -> Ordering+toOrdering PLT = LT+toOrdering PGT = GT+toOrdering PEQ = EQ+toOrdering Incomparable = error "incomparable items (this is a partial function)"
src/Numeric/Quaternion.hs view
@@ -1,14 +1,9 @@ ----------------------------------------------------------------------------- -- |--- Module : Numeric.Quaternion--- Copyright : (c) Artem Chirkin--- License : BSD3 ----- Maintainer : chirkin@arch.ethz.ch--- -- Quaternion operations implemented for Floats and Doubles. ----- The types `QDouble` and `QFloat` have the same representation as corresponding `Vector t 4`.+-- The types `QDouble` and `QFloat` have the same representation as corresponding @Vector t 4@. -- This means, you can do a cheap conversion between the types. -- -- However, arithmetic instances, such as Num and Floating are implemented in substentially different ways.@@ -19,17 +14,20 @@ -- -- All other numeric operations for vectors are element-wise, but for quaternions I have implemented -- the actual quaternion math.--- Some of the operations (such as trigonometric operations) are ambiguous for quaternions;--- the general rules I follow:------ 1. Preserve imaginary vector axis same if possible;--- 2. If both @+q@ and @-q@ are possible, prefer real value positive (@re q >= 0@).+-- In most of the cases, you can think of these as being operations on complex numbers,+-- where the role of imaginary @i@ is played by a 3D vector.+-- Some of the operations are ambiguous for quaternions;+-- for example \( \sqrt{-1} = \pm i \), but also \( \sqrt{-1} = \pm j \),+-- and \( \sqrt{-1} = \pm k \), and any other unit quaterion with zero real part.+-- In cases like this, I stick to the @i@-th axis: \( \sqrt{-1} := i \) ----------------------------------------------------------------------------- module Numeric.Quaternion ( Quaternion (..)+ , Quater(Quater) , QDouble, QFloat ) where -import Numeric.Quaternion.Class-import Numeric.Quaternion.QFloat-import Numeric.Quaternion.QDouble+import Numeric.DataFrame.Internal.Backend ()+import Numeric.Quaternion.Internal+import Numeric.Quaternion.Internal.QDouble+import Numeric.Quaternion.Internal.QFloat
− src/Numeric/Quaternion/Class.hs
@@ -1,85 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeFamilies #-}-module Numeric.Quaternion.Class- ( Quaternion (..)- ) where--import Numeric.Matrix (Matrix)-import Numeric.Vector (Vector)---- | Quaternion operations-class Quaternion t where- -- | Quaternion data type. The ordering of coordinates is @x y z w@,- -- where @w@ is an argument, and @x y z@ are components of a 3D vector- data Quater t- -- | Set the quaternion in format (x,y,z,w)- packQ :: t -> t -> t -> t -> Quater t- -- | Get the values of the quaternion in format (x,y,z,w)- unpackQ :: Quater t -> (t,t,t,t)- -- | Set the quaternion from 3D axis vector and argument- fromVecNum :: Vector t 3 -> t -> Quater t- -- | Set the quaternion from 4D vector in format (x,y,z,w)- fromVec4 :: Vector t 4 -> Quater t- -- | Transform the quaternion to 4D vector in format (x,y,z,w)- toVec4 :: Quater t -> Vector t 4- -- | Get scalar square of the quaternion.- --- -- >> realToFrac (square q) == q * conjugate q- square :: Quater t -> t- -- | Imagine part of quaternion (orientation vector)- im :: Quater t -> Quater t- -- | Real part of the quaternion- re :: Quater t -> Quater t- -- | Get imagenery 3D vector of the quaternion- imVec :: Quater t -> Vector t 3- -- | Real part of the quaternion into number- taker :: Quater t -> t- -- | i-th component- takei :: Quater t -> t- -- | j-th component- takej :: Quater t -> t- -- | k-th component- takek :: Quater t -> t- -- | Conjugate quaternion (negate imaginary part)- conjugate :: Quater t -> Quater t- -- | Rotates and scales vector in 3D using quaternion.- -- Let @q = (cos (a\/2), sin (a\/2) * v)@; then the rotation angle is @a@, and the axis of rotation is @v@.- -- Scaling is proportional to @|v|^2@.- --- -- >>> rotScale q x == q * x * (conjugate q)- rotScale :: Quater t -> Vector t 3 -> Vector t 3- -- | Creates a quaternion @q@ from two vectors @a@ and @b@.- -- @rotScale q a == b@- getRotScale :: Vector t 3 -> Vector t 3 -> Quater t- -- | Creates a rotation versor from an axis vector and an angle in radians.- -- Result is always a unit quaternion (versor).- -- If the argument vector is zero, then result is a real unit quaternion.- axisRotation :: Vector t 3 -> t -> Quater t- -- | Quaternion rotation angle- --- -- >>> q /= 0 ==> axisRotation (imVec q) (qArg q) == signum q- qArg :: Quater t -> t- -- | Create a quaternion from a rotation matrix.- -- Note, that rotations of `q` and `-q` are equivalent, there result of this function may be- -- ambiguious. I decided to force its real part be positive:- --- -- >>> taker (fromMatrix33 m) >= 0- fromMatrix33 :: Matrix t 3 3 -> Quater t- -- | Create a quaternion from a homogenious coordinates trasform matrix.- -- Ignores matrix translation transform.- -- Note, that rotations of `q` and `-q` are equivalent, there result of this function may be- -- ambiguious. I decided to force its real part be positive:- --- -- >>> taker (fromMatrix44 m) >= 0- fromMatrix44 :: Matrix t 4 4 -> Quater t- -- | Create a rotation matrix from a quaternion.- -- Note, that rotations of `q` and `-q` are equivalent, so the following property holds:- --- -- >>> toMatrix33 q == toMatrix33 (-q)- toMatrix33 :: Quater t -> Matrix t 3 3- -- | Create a homogenious coordinates trasform matrix from a quaternion.- -- Translation of the output matrix is zero.- -- Note, that rotations of `q` and `-q` are equivalent, so the following property holds:- --- -- >>> toMatrix44 q == toMatrix44 (-q)- toMatrix44 :: Quater t -> Matrix t 4 4
+ src/Numeric/Quaternion/Internal.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE ViewPatterns #-}+module Numeric.Quaternion.Internal+ ( Quaternion (..), Quater(Quater)+ ) where++import Numeric.Matrix.Internal (Matrix)+import Numeric.Vector.Internal (Vector)+import Text.Read++-- | @(x,y,z,w)@ of a quaternion+pattern Quater :: Quaternion t => t -> t -> t -> t -> Quater t+pattern Quater a b c d <- (unpackQ# -> (# a, b, c, d #))+ where+ Quater = packQ+{-# COMPLETE Quater #-}++-- | Quaternion operations+class Quaternion t where+ -- | Quaternion data type. The ordering of coordinates is @(x,y,z,w)@,+ -- where @w@ is the argument, and @x y z@ are the components of a 3D vector+ data Quater t+ -- | Set the quaternion in format @(x,y,z,w)@+ packQ :: t -> t -> t -> t -> Quater t+ -- | Get the values of the quaternion in format @(x,y,z,w)@+ unpackQ# :: Quater t -> (# t, t, t, t #)+ -- | Set the quaternion from 3D axis vector and argument+ fromVecNum :: Vector t 3 -> t -> Quater t+ -- | Set the quaternion from 4D vector in format @(x,y,z,w)@+ fromVec4 :: Vector t 4 -> Quater t+ -- | Transform the quaternion to 4D vector in format @(x,y,z,w)@+ toVec4 :: Quater t -> Vector t 4+ -- | Get scalar square of the quaternion.+ --+ -- >>> realToFrac (square q) == q * conjugate q+ square :: Quater t -> t+ -- | Imaginary part of the quaternion (orientation vector)+ im :: Quater t -> Quater t+ -- | Real part of the quaternion+ re :: Quater t -> Quater t+ -- | Imaginary part of the quaternion as a 3D vector+ imVec :: Quater t -> Vector t 3+ -- | Real part of the quaternion as a scalar+ taker :: Quater t -> t+ -- | i-th component+ takei :: Quater t -> t+ -- | j-th component+ takej :: Quater t -> t+ -- | k-th component+ takek :: Quater t -> t+ -- | Conjugate quaternion (negate imaginary part)+ conjugate :: Quater t -> Quater t+ -- | Rotates and scales vector in 3D using quaternion.+ -- Let \( q = c (\cos \frac{\alpha}{2}, v \sin \frac{\alpha}{2}) \)+ -- , \( c > 0 \), \( {|v|}^2 = 1 \);+ -- then the rotation angle is \( \alpha \), and the axis of rotation is \(v\).+ -- Scaling is proportional to \( c^2 \).+ --+ -- >>> rotScale q x == q * x * (conjugate q)+ rotScale :: Quater t -> Vector t 3 -> Vector t 3+ -- | Creates a quaternion @q@ from two vectors @a@ and @b@,+ -- such that @rotScale q a == b@.+ getRotScale :: Vector t 3 -> Vector t 3 -> Quater t+ -- | Creates a rotation versor from an axis vector and an angle in radians.+ -- Result is always a unit quaternion (versor).+ -- If the argument vector is zero, then result is a real unit quaternion.+ axisRotation :: Vector t 3 -> t -> Quater t+ -- | Quaternion rotation angle \( \alpha \)+ -- (where \( q = c (\cos \frac{\alpha}{2}, v \sin \frac{\alpha}{2}) \)+ -- , \( c > 0 \), \( {|v|}^2 = 1 \)).+ --+ -- >>> q /= 0 ==> axisRotation (imVec q) (qArg q) == signum q+ qArg :: Quater t -> t+ -- | Create a quaternion from a rotation matrix.+ -- Note, that rotations of \(q\) and \(-q\) are equivalent, there result of this+ -- function may be ambiguious. Assume the sign of the result to be chosen arbitrarily.+ fromMatrix33 :: Matrix t 3 3 -> Quater t+ -- | Create a quaternion from a homogenious coordinates trasform matrix.+ -- Ignores matrix translation transform.+ -- Note, that rotations of \(q\) and \(-q\) are equivalent, there result of this+ -- function may be ambiguious. Assume the sign of the result to be chosen arbitrarily.+ fromMatrix44 :: Matrix t 4 4 -> Quater t+ -- | Create a rotation matrix from a quaternion.+ -- Note, that rotations of \(q\) and \(-q\) are equivalent, so the following property holds:+ --+ -- >>> toMatrix33 q == toMatrix33 (-q)+ toMatrix33 :: Quater t -> Matrix t 3 3+ -- | Create a homogenious coordinates trasform matrix from a quaternion.+ -- Translation of the output matrix is zero.+ -- Note, that rotations of \(q\) and \(-q\) are equivalent, so the following property holds:+ --+ -- >>> toMatrix44 q == toMatrix44 (-q)+ toMatrix44 :: Quater t -> Matrix t 4 4+++instance (Show t, Quaternion t, Ord t, Num t) => Show (Quater t) where+ showsPrec p (Quater x y z w)+ = case finS of+ SEmpty -> showChar '0'+ Simple -> finF+ SParen -> showParen (p > 6) finF+ where+ (finS, finF) = go SEmpty+ [(w, Nothing), (x, Just 'i'), (y, Just 'j'), (z, Just 'k')]+ go :: ShowState -> [(t, Maybe Char)] -> (ShowState, ShowS)+ go s ((v,l):xs)+ | (s0, f0) <- showComponent s v l+ , (s', f') <- go s0 xs+ = (s', f0 . f')+ go s [] = (s, id)+ showLabel Nothing = id+ showLabel (Just c) = showChar c+ showComponent :: ShowState -> t -> Maybe Char -> (ShowState, ShowS)+ showComponent sState val mLabel = case (sState, compare val 0) of+ (_ , EQ) -> ( sState, id )+ (SEmpty, GT) -> ( Simple, shows val . showLabel mLabel )+ (SEmpty, LT) -> ( SParen, shows val . showLabel mLabel )+ (_ , GT) -> ( SParen+ , showString " + " . shows val . showLabel mLabel )+ (_ , LT) -> ( SParen+ , showString " - " . shows (negate val) . showLabel mLabel )+++data ShowState = SEmpty | Simple | SParen+ deriving Eq++instance (Read t, Quaternion t, Num t) => Read (Quater t) where+ readPrec = parens $ readPrec >>= go id 0 0 0 0+ where+ go :: (t -> t) -> t -> t -> t -> t -> t -> ReadPrec (Quater t)+ go f x y z w new =+ let def = pure (Quater x y z (f new))+ withLabel EOF = def+ withLabel (Ident "i")+ = (lexP >>= proceed (f new) y z w) <++ pure (Quater (f new) y z w)+ withLabel (Ident "j")+ = (lexP >>= proceed x (f new) z w) <++ pure (Quater x (f new) z w)+ withLabel (Ident "k")+ = (lexP >>= proceed x y (f new) w) <++ pure (Quater x y (f new) w)+ withLabel l = proceed x y z (f new) l+ in (lexP >>= withLabel) <++ def+ proceed :: t -> t -> t -> t -> Lexeme -> ReadPrec (Quater t)+ proceed x y z w (Symbol "+") = readPrec >>= go id x y z w+ proceed x y z w (Symbol "-") = readPrec >>= go negate x y z w+ proceed x y z w EOF = pure (Quater x y z w)+ proceed _ _ _ _ _ = pfail++ readListPrec = readListPrecDefault+ readList = readListDefault
+ src/Numeric/Quaternion/Internal/QDouble.hs view
@@ -0,0 +1,478 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Numeric.Quaternion.Internal.QDouble+ ( QDouble, Quater (..)+ ) where++import qualified Control.Monad.ST as ST+import Data.Coerce (coerce)+import Numeric.DataFrame.Internal.PrimArray+import qualified Numeric.DataFrame.ST as ST+import Numeric.DataFrame.Type+import Numeric.PrimBytes (PrimBytes)+import Numeric.Quaternion.Internal+import Numeric.Scalar.Internal+import Numeric.Vector.Internal++type QDouble = Quater Double++deriving instance PrimBytes (Quater Double)+deriving instance PrimArray Double (Quater Double)++instance Quaternion Double where+ newtype Quater Double = QDouble Vec4d+ {-# INLINE packQ #-}+ packQ = coerce (vec4 :: Double -> Double -> Double -> Double -> Vec4d)+ {-# INLINE unpackQ# #-}+ unpackQ# = coerce (unpackV4# :: Vec4d -> (# Double, Double, Double, Double #))+ {-# INLINE fromVecNum #-}+ fromVecNum (unpackV3# -> (# x, y, z #)) = packQ x y z+ {-# INLINE fromVec4 #-}+ fromVec4 = coerce+ {-# INLINE toVec4 #-}+ toVec4 = coerce+ {-# INLINE square #-}+ square (unpackQ# -> (# x, y, z, w #)) = (x * x) + (y * y) + (z * z) + (w * w)+ {-# INLINE im #-}+ im (unpackQ# -> (# x, y, z, _ #)) = packQ x y z 0.0+ {-# INLINE re #-}+ re (unpackQ# -> (# _, _, _, w #)) = packQ 0.0 0.0 0.0 w+ {-# INLINE imVec #-}+ imVec (unpackQ# -> (# x, y, z, _ #)) = vec3 x y z+ {-# INLINE taker #-}+ taker (unpackQ# -> (# _, _, _, w #)) = w+ {-# INLINE takei #-}+ takei (unpackQ# -> (# x, _, _, _ #)) = x+ {-# INLINE takej #-}+ takej (unpackQ# -> (# _, y, _, _ #)) = y+ {-# INLINE takek #-}+ takek (unpackQ# -> (# _, _, z, _ #)) = z+ {-# INLINE conjugate #-}+ conjugate (unpackQ# -> (# x, y, z, w #))+ = packQ (negate x) (negate y) (negate z) w+ {-# INLINE rotScale #-}+ rotScale (unpackQ# -> (# i, j, k, t #))+ (unpackV3# -> (# x, y, z #))+ = let l = t*t - i*i - j*j - k*k+ d = 2.0 * ( i*x + j*y + k*z)+ t2 = t * 2.0+ in vec3 (l*x + d*i + t2 * (z*j - y*k))+ (l*y + d*j + t2 * (x*k - z*i))+ (l*z + d*k + t2 * (y*i - x*j))+ {-# INLINE getRotScale #-}+ getRotScale a b = case (# unpackV3# a, unpackV3# b #) of+ (# _, (# 0, 0, 0 #) #) -> packQ 0.0 0.0 0.0 0.0+ (# (# 0, 0, 0 #), _ #) -> let x = (1 / 0 :: Double) in packQ x x x x+ (# (# a1, a2, a3 #), (# b1, b2, b3 #) #) ->+ let ma = sqrt (a1*a1 + a2*a2 + a3*a3)+ mb = sqrt (b1*b1 + b2*b2 + b3*b3)+ d = a1*b1 + a2*b2 + a3*b3+ c = sqrt (ma*mb + d)+ ma2 = ma * 1.4142135623730951 -- sqrt 2.0+ r = recip (ma2 * c)+ c' = sqrt (mb / ma) -- ratio of a and b for corner cases+ r' = recip (sqrt ( negate (a1*b1 + a2*b2) ))+ in case unpackV3# (cross a b) of+ (# 0, 0, 0 #)+ -- if a and b face the same direction, q is fully real+ | d >= 0 -> packQ 0 0 0 c'+ -- if a and b face opposite directions, find an orthogonal vector+ -- prerequisites: w == 0 and a·(x,y,z) == 0+ -- corner cases: only one vector component is non-zero+ | b1 == 0 -> packQ c' 0 0 0+ -- otherwise set the last component to zero,+ -- and get an orthogonal vector in 2D.+ | otherwise -> packQ (-b2*r') (b1*r') 0 0+ -- NB: here we have some precision troubles+ -- when a and b are close to parallel and opposite.+ (# t1, t2, t3 #) -> packQ (t1 * r) (t2 * r) (t3 * r) (c / ma2)+ {-# INLINE axisRotation #-}+ axisRotation v a = case unpackV3# v of+ (# 0, 0, 0 #) -> packQ 0.0 0.0 0.0 (if abs a < pi then 1 else -1)+ (# x, y, z #) ->+ let c = cos (a * 0.5)+ s = sin (a * 0.5)+ / sqrt (x*x + y*y + z*z)+ in packQ (x * s) (y * s) (z * s) c+ {-# INLINE qArg #-}+ qArg (unpackQ# -> (# x, y, z, w #)) = 2 * atan2 (sqrt (x*x + y*y + z*z)) w+ {-# INLINE fromMatrix33 #-}+ fromMatrix33 m = fromM 1+ (ix# 0# m) (ix# 1# m) (ix# 2# m)+ (ix# 3# m) (ix# 4# m) (ix# 5# m)+ (ix# 6# m) (ix# 7# m) (ix# 8# m)++ {-# INLINE fromMatrix44 #-}+ fromMatrix44 m = fromM (ix# 15# m)+ (ix# 0# m) (ix# 1# m) (ix# 2# m)+ (ix# 4# m) (ix# 5# m) (ix# 6# m)+ (ix# 8# m) (ix# 9# m) (ix# 10# m)++ {-# INLINE toMatrix33 #-}+ toMatrix33 (unpackQ# -> (# 0.0, 0.0, 0.0, w #))+ = let x = w * w+ f 0 = (# 3 :: Int , x #)+ f k = (# k-1, 0 #)+ in case gen# (CumulDims [9,3,1]) f 0 of+ (# _, m #) -> m -- diag (scalar (w * w))+ toMatrix33 (unpackQ# -> (# x', y', z', w' #)) =+ let x = scalar x'+ y = scalar y'+ z = scalar z'+ w = scalar w'+ x2 = x * x+ y2 = y * y+ z2 = z * z+ w2 = w * w+ l2 = x2 + y2 + z2 + w2+ in ST.runST $ do+ df <- ST.newDataFrame+ ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)+ ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)+ ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)+ ST.writeDataFrameOff df 3 $ 2*(x*y - z*w)+ ST.writeDataFrameOff df 4 $ l2 - 2*(z2 + x2)+ ST.writeDataFrameOff df 5 $ 2*(y*z + x*w)+ ST.writeDataFrameOff df 6 $ 2*(x*z + y*w)+ ST.writeDataFrameOff df 7 $ 2*(y*z - x*w)+ ST.writeDataFrameOff df 8 $ l2 - 2*(y2 + x2)+ ST.unsafeFreezeDataFrame df+ {-# INLINE toMatrix44 #-}+ toMatrix44 (unpackQ# -> (# 0.0, 0.0, 0.0, w #)) = ST.runST $ do+ df <- ST.newDataFrame+ mapM_ (flip (ST.writeDataFrameOff df) 0) [0..15]+ let w2 = scalar (w * w)+ ST.writeDataFrameOff df 0 w2+ ST.writeDataFrameOff df 5 w2+ ST.writeDataFrameOff df 10 w2+ ST.writeDataFrameOff df 15 1+ ST.unsafeFreezeDataFrame df+ toMatrix44 (unpackQ# -> (# x', y', z', w' #)) =+ let x = scalar x'+ y = scalar y'+ z = scalar z'+ w = scalar w'+ x2 = x * x+ y2 = y * y+ z2 = z * z+ w2 = w * w+ l2 = x2 + y2 + z2 + w2+ in ST.runST $ do+ df <- ST.newDataFrame+ ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)+ ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)+ ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)+ ST.writeDataFrameOff df 3 0+ ST.writeDataFrameOff df 4 $ 2*(x*y - z*w)+ ST.writeDataFrameOff df 5 $ l2 - 2*(z2 + x2)+ ST.writeDataFrameOff df 6 $ 2*(y*z + x*w)+ ST.writeDataFrameOff df 7 0+ ST.writeDataFrameOff df 8 $ 2*(x*z + y*w)+ ST.writeDataFrameOff df 9 $ 2*(y*z - x*w)+ ST.writeDataFrameOff df 10 $ l2 - 2*(y2 + x2)+ ST.writeDataFrameOff df 11 0+ ST.writeDataFrameOff df 12 0+ ST.writeDataFrameOff df 13 0+ ST.writeDataFrameOff df 14 0+ ST.writeDataFrameOff df 15 1+ ST.unsafeFreezeDataFrame df+++{- Calculate quaternion from a 3x3 matrix.++ First argument is a constant; it is either 1 for a 3x3 matrix,+ or m44 for a 4x4 matrix. I just need to multiply all components by+ this number.++ Further NB for the formulae:++ d == square q == det m ** (1/3)+ t == trace m == 4 w w - d+ m01 - m10 == 4 z w+ m20 - m02 == 4 y w+ m12 - m21 == 4 x w+ m01 + m10 == 4 x y+ m20 + m02 == 4 x z+ m12 + m21 == 4 y z+ m00 == + x x - y y - z z + w w+ m11 == - x x + y y - z z + w w+ m22 == - x x - y y + z z + w w+ 4 x x == d + m00 - m11 - m22+ 4 y y == d - m00 + m11 - m22+ 4 z z == d - m00 - m11 + m22+ 4 w w == d + m00 + m11 + m22+ -}+fromM :: Double+ -> Double -> Double -> Double+ -> Double -> Double -> Double+ -> Double -> Double -> Double+ -> QDouble+fromM c'+ m00 m01 m02+ m10 m11 m12+ m20 m21 m22+ | t > 0+ = let dd = sqrt ( d + t )+ is = c / dd+ in packQ ((m12 - m21)*is) ((m20 - m02)*is) ((m01 - m10)*is) (c*dd)+ | m00 > m11 && m00 > m22+ = let dd = sqrt ( d + m00 - m11 - m22 )+ is = c / dd+ in packQ (c*dd) ((m01 + m10)*is) ((m02 + m20)*is) ((m12 - m21)*is)+ | m11 > m22+ = let dd = sqrt ( d - m00 + m11 - m22 )+ is = c / dd+ in packQ ((m01 + m10)*is) (c*dd) ((m12 + m21)*is) ((m20 - m02)*is)+ | otherwise+ = let dd = sqrt ( d - m00 - m11 + m22 )+ is = c / dd+ in packQ ((m02 + m20)*is) ((m12 + m21)*is) (c*dd) ((m01 - m10)*is)++ where+ -- normalizing constant+ c = recip $ 2 * sqrt c'+ -- trace+ t = m00 + m11 + m22+ -- cubic root of determinant+ d = ( m00 * ( m11 * m22 - m12 * m21 )+ - m01 * ( m10 * m22 - m12 * m20 )+ + m02 * ( m10 * m21 - m11 * m20 )+ ) ** 0.33333333333333333333333333333333+++++instance Num QDouble where+ QDouble a + QDouble b+ = QDouble (a + b)+ {-# INLINE (+) #-}+ QDouble a - QDouble b+ = QDouble (a - b)+ {-# INLINE (-) #-}+ (unpackQ# -> (# a1, a2, a3, a4 #)) * (unpackQ# -> (# b1, b2, b3, b4 #))+ = packQ+ ((a4 * b1) ++ (a1 * b4) ++ (a2 * b3) -+ (a3 * b2)+ )+ ((a4 * b2) -+ (a1 * b3) ++ (a2 * b4) ++ (a3 * b1)+ )+ ((a4 * b3) ++ (a1 * b2) -+ (a2 * b1) ++ (a3 * b4)+ )+ ((a4 * b4) -+ (a1 * b1) -+ (a2 * b2) -+ (a3 * b3)+ )+ {-# INLINE (*) #-}+ negate (QDouble a) = QDouble (negate a)+ {-# INLINE negate #-}+ abs = packQ 0.0 0.0 0.0 . sqrt . square+ {-# INLINE abs #-}+ signum q@(unpackQ# -> (# x, y, z, w #))+ = case square q of+ 0.0 -> packQ 0.0 0.0 0.0 0.0+ qd -> case recip (sqrt qd) of+ s -> packQ (x * s) (y * s) (z * s) (w * s)+ {-# INLINE signum #-}+ fromInteger = packQ 0.0 0.0 0.0 . fromInteger+ {-# INLINE fromInteger #-}+++instance Fractional QDouble where+ {-# INLINE recip #-}+ recip q@(unpackQ# -> (# x, y, z, w #)) = case negate (recip (square q)) of+ c -> packQ (x * c) (y * c) (z * c) (negate (w * c))+ {-# INLINE (/) #-}+ a / b = a * recip b+ {-# INLINE fromRational #-}+ fromRational = packQ 0.0 0.0 0.0 . fromRational+++instance Floating QDouble where+ {-# INLINE pi #-}+ pi = packQ 0.0 0.0 0.0 3.141592653589793+ {-# INLINE exp #-}+ exp (unpackQ# -> (# x, y, z, w #))+ = case (# (x * x) ++ (y * y) ++ (z * z)+ , exp w+ #) of+ (# 0.0, et #) -> packQ 0.0 0.0 0.0 et+ (# mv2, et #) -> case sqrt mv2 of+ mv -> case et * sin mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (et * cos mv)+ {-# INLINE log #-}+ log = log' (Vec3 1 0 0)+ {-# INLINE sqrt #-}+ sqrt = sqrt' (Vec3 1 0 0)+ {-# INLINE sin #-}+ sin (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (sin w)+ mv2 -> case sqrt mv2 of+ mv -> case cos w * sinh mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (sin w * cosh mv)+ {-# INLINE cos #-}+ cos (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (cos w)+ mv2 -> case sqrt mv2 of+ mv -> case sin w * sinh mv / negate mv of+ l -> packQ (x * l) (y * l) (z * l) (cos w * cosh mv)+ {-# INLINE tan #-}+ tan (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (tan w)+ mv2 ->+ let mv = sqrt mv2+ chv = cosh mv+ shv = sinh mv+ ct = cos w+ st = sin w+ cq = recip ( (ct * ct * chv * chv) + (st * st * shv * shv) )+ l = chv * shv * cq / mv+ in packQ (x * l) (y * l) (z * l) (ct * st * cq)+ {-# INLINE sinh #-}+ sinh (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (sinh w)+ mv2 -> case sqrt mv2 of+ mv -> case cosh w * sin mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (sinh w * cos mv)+ {-# INLINE cosh #-}+ cosh (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (cosh w)+ mv2 -> case sqrt mv2 of+ mv -> case sinh w * sin mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (cosh w * cos mv)+ {-# INLINE tanh #-}+ tanh (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (tanh w)+ mv2 ->+ let mv = sqrt mv2+ cv = cos mv+ sv = sin mv+ cht = cosh w+ sht = sinh w+ cq = recip ( (cht * cht * cv * cv) + (sht * sht * sv * sv) )+ l = cv * sv * cq / mv+ in packQ (x * l) (y * l) (z * l) (cht * sht * cq)+ {-# INLINE asin #-}+ asin q = -i * log' axis (i*q + sqrt' axis (1 - q*q))+ where+ axis = sigVec q+ i = fromVecNum axis 0+ {-# INLINE acos #-}+ acos q = pi/2 - asin q+ {-# INLINE atan #-}+ -- atan q = i / 2 * log ( (i + q) / (i - q) )+ atan (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0 -> packQ 0 0 0 (atan w)+ v2 ->+ let v = sqrt v2+ w2 = w*w+ vw2 = w2 + v2+ t = 1 + vw2+ c = 0.25 * log ((t + 2*v) / (t - 2*v)) / v+ in packQ (c*x) (c*y) (c*z) $ 0.5 * atan2 (2*w) (1 - vw2)+ {-# INLINE asinh #-}+ -- The original formula:+ -- asinh q = log (q + sqrt (q*q + 1))+ -- below is a more numerically stable version.+ asinh (unpackQ# -> (# x, y, z, w #))+ | v2 == 0+ = packQ 0 0 0 (asinh w)+ | w == 0+ = if v2 <= 1+ then let c = asin v / v+ in packQ (c*x) (c*y) (c*z) 0+ else let c = 0.5 * pi / v+ w' = 0.5 * log (2*v2 - 1 + 2 * v * sqrt ( v2 - 1 ))+ in packQ (c*x) (c*y) (c*z) w'+ | otherwise+ = let c = atan2 v t / v+ w' = 0.5 * log ( t2 + v2) - log t+ + if w >= 0+ then log ( t + w )+ else log 2 + log w2 - log ( t - w ) - log ( r + w2 + v2 - 1 )+ in packQ (c*x) (c*y) (c*z) w'+ where+ v2 = (x * x) + (y * y) + (z * z)+ v = sqrt v2+ w2 = w*w+ wvp1 = w2 - v2 + 1+ r = sqrt $ wvp1*wvp1 + 4*w2*v2+ t = sqrt $ ( r + wvp1 ) * 0.5+ t2 = t*t+ {-# INLINE acosh #-}+ -- note, log (q + sqrt (q*q - 1)) would not work, because that would not+ -- be the principal value.+ acosh q = log' axis (q + sqrt' axis (q + 1) * sqrt' axis (q - 1))+ where+ axis = sigVec q+ {-# INLINE atanh #-}+ atanh q = 0.5 * log' (sigVec q) ((1+q)/(1-q))++-- If q is negative real, provide a fallback axis to align log.+log' :: Vec3d -> QDouble -> QDouble+log' r (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 | w >= 0+ -> packQ 0.0 0.0 0.0 (log w)+ | Vec3 rx ry rz <- r+ -> packQ (pi*rx) (pi*ry) (pi*rz) (log (negate w))+ mv2 -> case (# sqrt (mv2 + (w * w)), sqrt mv2 #) of+ (# mq, mv #) -> case atan2 mv w / mv of+ l -> packQ (x * l) (y * l) (z * l) (log mq)+++-- If q is negative real, provide a fallback axis to align sqrt.+sqrt' :: Vec3d -> QDouble -> QDouble+sqrt' r (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 | w >= 0+ -> packQ 0.0 0.0 0.0 (sqrt w)+ | Vec3 rx ry rz <- r+ , sw <- sqrt (negate w)+ -> packQ (sw*rx) (sw*ry) (sw*rz) 0+ mv2 ->+ let mq = sqrt (mv2 + w * w)+ l2 = sqrt mq+ tq = w / (mq * 2.0)+ sina = sqrt (0.5 - tq) * l2 / sqrt mv2+ in packQ (x * sina) (y * sina) (z * sina) (sqrt (0.5 + tq) * l2)++sigVec :: QDouble -> Vec3d+sigVec (unpackQ# -> (# x, y, z, _ #))+ = case sqrt ((x * x) + (y * y) + (z * z)) of+ 0 -> vec3 1 0 0+ l -> vec3 (x/l) (y/l) (z/l)++instance Eq QDouble where+ {-# INLINE (==) #-}+ QDouble a == QDouble b = a == b+ {-# INLINE (/=) #-}+ QDouble a /= QDouble b = a /= b
+ src/Numeric/Quaternion/Internal/QFloat.hs view
@@ -0,0 +1,478 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Numeric.Quaternion.Internal.QFloat+ ( QFloat, Quater (..)+ ) where++import qualified Control.Monad.ST as ST+import Data.Coerce (coerce)+import Numeric.DataFrame.Internal.PrimArray+import qualified Numeric.DataFrame.ST as ST+import Numeric.DataFrame.Type+import Numeric.PrimBytes (PrimBytes)+import Numeric.Quaternion.Internal+import Numeric.Scalar.Internal+import Numeric.Vector.Internal++type QFloat = Quater Float++deriving instance PrimBytes (Quater Float)+deriving instance PrimArray Float (Quater Float)++instance Quaternion Float where+ newtype Quater Float = QFloat Vec4f+ {-# INLINE packQ #-}+ packQ = coerce (vec4 :: Float -> Float -> Float -> Float -> Vec4f)+ {-# INLINE unpackQ# #-}+ unpackQ# = coerce (unpackV4# :: Vec4f -> (# Float, Float, Float, Float #))+ {-# INLINE fromVecNum #-}+ fromVecNum (unpackV3# -> (# x, y, z #)) = packQ x y z+ {-# INLINE fromVec4 #-}+ fromVec4 = coerce+ {-# INLINE toVec4 #-}+ toVec4 = coerce+ {-# INLINE square #-}+ square (unpackQ# -> (# x, y, z, w #)) = (x * x) + (y * y) + (z * z) + (w * w)+ {-# INLINE im #-}+ im (unpackQ# -> (# x, y, z, _ #)) = packQ x y z 0.0+ {-# INLINE re #-}+ re (unpackQ# -> (# _, _, _, w #)) = packQ 0.0 0.0 0.0 w+ {-# INLINE imVec #-}+ imVec (unpackQ# -> (# x, y, z, _ #)) = vec3 x y z+ {-# INLINE taker #-}+ taker (unpackQ# -> (# _, _, _, w #)) = w+ {-# INLINE takei #-}+ takei (unpackQ# -> (# x, _, _, _ #)) = x+ {-# INLINE takej #-}+ takej (unpackQ# -> (# _, y, _, _ #)) = y+ {-# INLINE takek #-}+ takek (unpackQ# -> (# _, _, z, _ #)) = z+ {-# INLINE conjugate #-}+ conjugate (unpackQ# -> (# x, y, z, w #))+ = packQ (negate x) (negate y) (negate z) w+ {-# INLINE rotScale #-}+ rotScale (unpackQ# -> (# i, j, k, t #))+ (unpackV3# -> (# x, y, z #))+ = let l = t*t - i*i - j*j - k*k+ d = 2.0 * ( i*x + j*y + k*z)+ t2 = t * 2.0+ in vec3 (l*x + d*i + t2 * (z*j - y*k))+ (l*y + d*j + t2 * (x*k - z*i))+ (l*z + d*k + t2 * (y*i - x*j))+ {-# INLINE getRotScale #-}+ getRotScale a b = case (# unpackV3# a, unpackV3# b #) of+ (# _, (# 0, 0, 0 #) #) -> packQ 0.0 0.0 0.0 0.0+ (# (# 0, 0, 0 #), _ #) -> let x = (1 / 0 :: Float) in packQ x x x x+ (# (# a1, a2, a3 #), (# b1, b2, b3 #) #) ->+ let ma = sqrt (a1*a1 + a2*a2 + a3*a3)+ mb = sqrt (b1*b1 + b2*b2 + b3*b3)+ d = a1*b1 + a2*b2 + a3*b3+ c = sqrt (ma*mb + d)+ ma2 = ma * 1.4142135623730951 -- sqrt 2.0+ r = recip (ma2 * c)+ c' = sqrt (mb / ma) -- ratio of a and b for corner cases+ r' = recip (sqrt ( negate (a1*b1 + a2*b2) ))+ in case unpackV3# (cross a b) of+ (# 0, 0, 0 #)+ -- if a and b face the same direction, q is fully real+ | d >= 0 -> packQ 0 0 0 c'+ -- if a and b face opposite directions, find an orthogonal vector+ -- prerequisites: w == 0 and a·(x,y,z) == 0+ -- corner cases: only one vector component is non-zero+ | b1 == 0 -> packQ c' 0 0 0+ -- otherwise set the last component to zero,+ -- and get an orthogonal vector in 2D.+ | otherwise -> packQ (-b2*r') (b1*r') 0 0+ -- NB: here we have some precision troubles+ -- when a and b are close to parallel and opposite.+ (# t1, t2, t3 #) -> packQ (t1 * r) (t2 * r) (t3 * r) (c / ma2)+ {-# INLINE axisRotation #-}+ axisRotation v a = case unpackV3# v of+ (# 0, 0, 0 #) -> packQ 0.0 0.0 0.0 (if abs a < pi then 1 else -1)+ (# x, y, z #) ->+ let c = cos (a * 0.5)+ s = sin (a * 0.5)+ / sqrt (x*x + y*y + z*z)+ in packQ (x * s) (y * s) (z * s) c+ {-# INLINE qArg #-}+ qArg (unpackQ# -> (# x, y, z, w #)) = 2 * atan2 (sqrt (x*x + y*y + z*z)) w+ {-# INLINE fromMatrix33 #-}+ fromMatrix33 m = fromM 1+ (ix# 0# m) (ix# 1# m) (ix# 2# m)+ (ix# 3# m) (ix# 4# m) (ix# 5# m)+ (ix# 6# m) (ix# 7# m) (ix# 8# m)++ {-# INLINE fromMatrix44 #-}+ fromMatrix44 m = fromM (ix# 15# m)+ (ix# 0# m) (ix# 1# m) (ix# 2# m)+ (ix# 4# m) (ix# 5# m) (ix# 6# m)+ (ix# 8# m) (ix# 9# m) (ix# 10# m)++ {-# INLINE toMatrix33 #-}+ toMatrix33 (unpackQ# -> (# 0.0, 0.0, 0.0, w #))+ = let x = w * w+ f 0 = (# 3 :: Int , x #)+ f k = (# k-1, 0 #)+ in case gen# (CumulDims [9,3,1]) f 0 of+ (# _, m #) -> m -- diag (scalar (w * w))+ toMatrix33 (unpackQ# -> (# x', y', z', w' #)) =+ let x = scalar x'+ y = scalar y'+ z = scalar z'+ w = scalar w'+ x2 = x * x+ y2 = y * y+ z2 = z * z+ w2 = w * w+ l2 = x2 + y2 + z2 + w2+ in ST.runST $ do+ df <- ST.newDataFrame+ ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)+ ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)+ ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)+ ST.writeDataFrameOff df 3 $ 2*(x*y - z*w)+ ST.writeDataFrameOff df 4 $ l2 - 2*(z2 + x2)+ ST.writeDataFrameOff df 5 $ 2*(y*z + x*w)+ ST.writeDataFrameOff df 6 $ 2*(x*z + y*w)+ ST.writeDataFrameOff df 7 $ 2*(y*z - x*w)+ ST.writeDataFrameOff df 8 $ l2 - 2*(y2 + x2)+ ST.unsafeFreezeDataFrame df+ {-# INLINE toMatrix44 #-}+ toMatrix44 (unpackQ# -> (# 0.0, 0.0, 0.0, w #)) = ST.runST $ do+ df <- ST.newDataFrame+ mapM_ (flip (ST.writeDataFrameOff df) 0) [0..15]+ let w2 = scalar (w * w)+ ST.writeDataFrameOff df 0 w2+ ST.writeDataFrameOff df 5 w2+ ST.writeDataFrameOff df 10 w2+ ST.writeDataFrameOff df 15 1+ ST.unsafeFreezeDataFrame df+ toMatrix44 (unpackQ# -> (# x', y', z', w' #)) =+ let x = scalar x'+ y = scalar y'+ z = scalar z'+ w = scalar w'+ x2 = x * x+ y2 = y * y+ z2 = z * z+ w2 = w * w+ l2 = x2 + y2 + z2 + w2+ in ST.runST $ do+ df <- ST.newDataFrame+ ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)+ ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)+ ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)+ ST.writeDataFrameOff df 3 0+ ST.writeDataFrameOff df 4 $ 2*(x*y - z*w)+ ST.writeDataFrameOff df 5 $ l2 - 2*(z2 + x2)+ ST.writeDataFrameOff df 6 $ 2*(y*z + x*w)+ ST.writeDataFrameOff df 7 0+ ST.writeDataFrameOff df 8 $ 2*(x*z + y*w)+ ST.writeDataFrameOff df 9 $ 2*(y*z - x*w)+ ST.writeDataFrameOff df 10 $ l2 - 2*(y2 + x2)+ ST.writeDataFrameOff df 11 0+ ST.writeDataFrameOff df 12 0+ ST.writeDataFrameOff df 13 0+ ST.writeDataFrameOff df 14 0+ ST.writeDataFrameOff df 15 1+ ST.unsafeFreezeDataFrame df+++{- Calculate quaternion from a 3x3 matrix.++ First argument is a constant; it is either 1 for a 3x3 matrix,+ or m44 for a 4x4 matrix. I just need to multiply all components by+ this number.++ Further NB for the formulae:++ d == square q == det m ** (1/3)+ t == trace m == 4 w w - d+ m01 - m10 == 4 z w+ m20 - m02 == 4 y w+ m12 - m21 == 4 x w+ m01 + m10 == 4 x y+ m20 + m02 == 4 x z+ m12 + m21 == 4 y z+ m00 == + x x - y y - z z + w w+ m11 == - x x + y y - z z + w w+ m22 == - x x - y y + z z + w w+ 4 x x == d + m00 - m11 - m22+ 4 y y == d - m00 + m11 - m22+ 4 z z == d - m00 - m11 + m22+ 4 w w == d + m00 + m11 + m22+ -}+fromM :: Float+ -> Float -> Float -> Float+ -> Float -> Float -> Float+ -> Float -> Float -> Float+ -> QFloat+fromM c'+ m00 m01 m02+ m10 m11 m12+ m20 m21 m22+ | t > 0+ = let dd = sqrt ( d + t )+ is = c / dd+ in packQ ((m12 - m21)*is) ((m20 - m02)*is) ((m01 - m10)*is) (c*dd)+ | m00 > m11 && m00 > m22+ = let dd = sqrt ( d + m00 - m11 - m22 )+ is = c / dd+ in packQ (c*dd) ((m01 + m10)*is) ((m02 + m20)*is) ((m12 - m21)*is)+ | m11 > m22+ = let dd = sqrt ( d - m00 + m11 - m22 )+ is = c / dd+ in packQ ((m01 + m10)*is) (c*dd) ((m12 + m21)*is) ((m20 - m02)*is)+ | otherwise+ = let dd = sqrt ( d - m00 - m11 + m22 )+ is = c / dd+ in packQ ((m02 + m20)*is) ((m12 + m21)*is) (c*dd) ((m01 - m10)*is)++ where+ -- normalizing constant+ c = recip $ 2 * sqrt c'+ -- trace+ t = m00 + m11 + m22+ -- cubic root of determinant+ d = ( m00 * ( m11 * m22 - m12 * m21 )+ - m01 * ( m10 * m22 - m12 * m20 )+ + m02 * ( m10 * m21 - m11 * m20 )+ ) ** 0.33333333333333333333333333333333+++++instance Num QFloat where+ QFloat a + QFloat b+ = QFloat (a + b)+ {-# INLINE (+) #-}+ QFloat a - QFloat b+ = QFloat (a - b)+ {-# INLINE (-) #-}+ (unpackQ# -> (# a1, a2, a3, a4 #)) * (unpackQ# -> (# b1, b2, b3, b4 #))+ = packQ+ ((a4 * b1) ++ (a1 * b4) ++ (a2 * b3) -+ (a3 * b2)+ )+ ((a4 * b2) -+ (a1 * b3) ++ (a2 * b4) ++ (a3 * b1)+ )+ ((a4 * b3) ++ (a1 * b2) -+ (a2 * b1) ++ (a3 * b4)+ )+ ((a4 * b4) -+ (a1 * b1) -+ (a2 * b2) -+ (a3 * b3)+ )+ {-# INLINE (*) #-}+ negate (QFloat a) = QFloat (negate a)+ {-# INLINE negate #-}+ abs = packQ 0.0 0.0 0.0 . sqrt . square+ {-# INLINE abs #-}+ signum q@(unpackQ# -> (# x, y, z, w #))+ = case square q of+ 0.0 -> packQ 0.0 0.0 0.0 0.0+ qd -> case recip (sqrt qd) of+ s -> packQ (x * s) (y * s) (z * s) (w * s)+ {-# INLINE signum #-}+ fromInteger = packQ 0.0 0.0 0.0 . fromInteger+ {-# INLINE fromInteger #-}+++instance Fractional QFloat where+ {-# INLINE recip #-}+ recip q@(unpackQ# -> (# x, y, z, w #)) = case negate (recip (square q)) of+ c -> packQ (x * c) (y * c) (z * c) (negate (w * c))+ {-# INLINE (/) #-}+ a / b = a * recip b+ {-# INLINE fromRational #-}+ fromRational = packQ 0.0 0.0 0.0 . fromRational+++instance Floating QFloat where+ {-# INLINE pi #-}+ pi = packQ 0.0 0.0 0.0 3.141592653589793+ {-# INLINE exp #-}+ exp (unpackQ# -> (# x, y, z, w #))+ = case (# (x * x) ++ (y * y) ++ (z * z)+ , exp w+ #) of+ (# 0.0, et #) -> packQ 0.0 0.0 0.0 et+ (# mv2, et #) -> case sqrt mv2 of+ mv -> case et * sin mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (et * cos mv)+ {-# INLINE log #-}+ log = log' (Vec3 1 0 0)+ {-# INLINE sqrt #-}+ sqrt = sqrt' (Vec3 1 0 0)+ {-# INLINE sin #-}+ sin (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (sin w)+ mv2 -> case sqrt mv2 of+ mv -> case cos w * sinh mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (sin w * cosh mv)+ {-# INLINE cos #-}+ cos (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (cos w)+ mv2 -> case sqrt mv2 of+ mv -> case sin w * sinh mv / negate mv of+ l -> packQ (x * l) (y * l) (z * l) (cos w * cosh mv)+ {-# INLINE tan #-}+ tan (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (tan w)+ mv2 ->+ let mv = sqrt mv2+ chv = cosh mv+ shv = sinh mv+ ct = cos w+ st = sin w+ cq = recip ( (ct * ct * chv * chv) + (st * st * shv * shv) )+ l = chv * shv * cq / mv+ in packQ (x * l) (y * l) (z * l) (ct * st * cq)+ {-# INLINE sinh #-}+ sinh (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (sinh w)+ mv2 -> case sqrt mv2 of+ mv -> case cosh w * sin mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (sinh w * cos mv)+ {-# INLINE cosh #-}+ cosh (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (cosh w)+ mv2 -> case sqrt mv2 of+ mv -> case sinh w * sin mv / mv of+ l -> packQ (x * l) (y * l) (z * l) (cosh w * cos mv)+ {-# INLINE tanh #-}+ tanh (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 -> packQ 0.0 0.0 0.0 (tanh w)+ mv2 ->+ let mv = sqrt mv2+ cv = cos mv+ sv = sin mv+ cht = cosh w+ sht = sinh w+ cq = recip ( (cht * cht * cv * cv) + (sht * sht * sv * sv) )+ l = cv * sv * cq / mv+ in packQ (x * l) (y * l) (z * l) (cht * sht * cq)+ {-# INLINE asin #-}+ asin q = -i * log' axis (i*q + sqrt' axis (1 - q*q))+ where+ axis = sigVec q+ i = fromVecNum axis 0+ {-# INLINE acos #-}+ acos q = pi/2 - asin q+ {-# INLINE atan #-}+ -- atan q = i / 2 * log ( (i + q) / (i - q) )+ atan (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0 -> packQ 0 0 0 (atan w)+ v2 ->+ let v = sqrt v2+ w2 = w*w+ vw2 = w2 + v2+ t = 1 + vw2+ c = 0.25 * log ((t + 2*v) / (t - 2*v)) / v+ in packQ (c*x) (c*y) (c*z) $ 0.5 * atan2 (2*w) (1 - vw2)+ {-# INLINE asinh #-}+ -- The original formula:+ -- asinh q = log (q + sqrt (q*q + 1))+ -- below is a more numerically stable version.+ asinh (unpackQ# -> (# x, y, z, w #))+ | v2 == 0+ = packQ 0 0 0 (asinh w)+ | w == 0+ = if v2 <= 1+ then let c = asin v / v+ in packQ (c*x) (c*y) (c*z) 0+ else let c = 0.5 * pi / v+ w' = 0.5 * log (2*v2 - 1 + 2 * v * sqrt ( v2 - 1 ))+ in packQ (c*x) (c*y) (c*z) w'+ | otherwise+ = let c = atan2 v t / v+ w' = 0.5 * log ( t2 + v2) - log t+ + if w >= 0+ then log ( t + w )+ else log 2 + log w2 - log ( t - w ) - log ( r + w2 + v2 - 1 )+ in packQ (c*x) (c*y) (c*z) w'+ where+ v2 = (x * x) + (y * y) + (z * z)+ v = sqrt v2+ w2 = w*w+ wvp1 = w2 - v2 + 1+ r = sqrt $ wvp1*wvp1 + 4*w2*v2+ t = sqrt $ ( r + wvp1 ) * 0.5+ t2 = t*t+ {-# INLINE acosh #-}+ -- note, log (q + sqrt (q*q - 1)) would not work, because that would not+ -- be the principal value.+ acosh q = log' axis (q + sqrt' axis (q + 1) * sqrt' axis (q - 1))+ where+ axis = sigVec q+ {-# INLINE atanh #-}+ atanh q = 0.5 * log ((1+q)/(1-q))++-- If q is negative real, provide a fallback axis to align log.+log' :: Vec3f -> QFloat -> QFloat+log' r (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 | w >= 0+ -> packQ 0.0 0.0 0.0 (log w)+ | Vec3 rx ry rz <- r+ -> packQ (pi*rx) (pi*ry) (pi*rz) (log (negate w))+ mv2 -> case (# sqrt (mv2 + (w * w)), sqrt mv2 #) of+ (# mq, mv #) -> case atan2 mv w / mv of+ l -> packQ (x * l) (y * l) (z * l) (log mq)+++-- If q is negative real, provide a fallback axis to align sqrt.+sqrt' :: Vec3f -> QFloat -> QFloat+sqrt' r (unpackQ# -> (# x, y, z, w #))+ = case (x * x) + (y * y) + (z * z) of+ 0.0 | w >= 0+ -> packQ 0.0 0.0 0.0 (sqrt w)+ | Vec3 rx ry rz <- r+ , sw <- sqrt (negate w)+ -> packQ (sw*rx) (sw*ry) (sw*rz) 0+ mv2 ->+ let mq = sqrt (mv2 + w * w)+ l2 = sqrt mq+ tq = w / (mq * 2.0)+ sina = sqrt (0.5 - tq) * l2 / sqrt mv2+ in packQ (x * sina) (y * sina) (z * sina) (sqrt (0.5 + tq) * l2)++sigVec :: QFloat -> Vec3f+sigVec (unpackQ# -> (# x, y, z, _ #))+ = case sqrt ((x * x) + (y * y) + (z * z)) of+ 0 -> vec3 1 0 0+ l -> vec3 (x/l) (y/l) (z/l)++instance Eq QFloat where+ {-# INLINE (==) #-}+ QFloat a == QFloat b = a == b+ {-# INLINE (/=) #-}+ QFloat a /= QFloat b = a /= b
− src/Numeric/Quaternion/QDouble.hs
@@ -1,559 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE UnboxedTuples #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Numeric.Quaternion.QDouble- ( QDouble, Quater (..)- ) where--import Data.Coerce (coerce)-import GHC.Exts--import qualified Control.Monad.ST as ST-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.Family.DoubleX3-import Numeric.DataFrame.Internal.Array.Family.DoubleX4-import qualified Numeric.DataFrame.ST as ST-import Numeric.DataFrame.Type-import Numeric.Dimensions-import qualified Numeric.Dimensions.Fold as ST-import Numeric.PrimBytes (PrimBytes)-import Numeric.Quaternion.Class-import Numeric.Scalar-import Numeric.Vector---type QDouble = Quater Double--deriving instance PrimBytes (Quater Double)-deriving instance PrimArray Double (Quater Double)--instance Quaternion Double where- newtype Quater Double = QDouble DoubleX4- {-# INLINE packQ #-}- packQ (D# x) (D# y) (D# z) (D# w) = QDouble (DoubleX4# x y z w)- {-# INLINE unpackQ #-}- unpackQ (QDouble (DoubleX4# x y z w)) = (D# x, D# y, D# z, D# w)- {-# INLINE fromVecNum #-}- fromVecNum (SingleFrame (DoubleX3# x y z)) (D# w) = QDouble (DoubleX4# x y z w)- {-# INLINE fromVec4 #-}- fromVec4 = coerce- {-# INLINE toVec4 #-}- toVec4 = coerce- {-# INLINE square #-}- square q = D# (qdot q)- {-# INLINE im #-}- im (QDouble (DoubleX4# x y z _)) = QDouble (DoubleX4# x y z 0.0##)- {-# INLINE re #-}- re (QDouble (DoubleX4# _ _ _ w)) = QDouble (DoubleX4# 0.0## 0.0## 0.0## w)- {-# INLINE imVec #-}- imVec (QDouble (DoubleX4# x y z _)) = SingleFrame (DoubleX3# x y z)- {-# INLINE taker #-}- taker (QDouble (DoubleX4# _ _ _ w)) = D# w- {-# INLINE takei #-}- takei (QDouble (DoubleX4# x _ _ _)) = D# x- {-# INLINE takej #-}- takej (QDouble (DoubleX4# _ y _ _)) = D# y- {-# INLINE takek #-}- takek (QDouble (DoubleX4# _ _ z _)) = D# z- {-# INLINE conjugate #-}- conjugate (QDouble (DoubleX4# x y z w)) = QDouble (DoubleX4#- (negateDouble# x)- (negateDouble# y)- (negateDouble# z) w)- {-# INLINE rotScale #-}- rotScale (QDouble (DoubleX4# i j k t))- (SingleFrame (DoubleX3# x y z))- = let l = t*##t -## i*##i -## j*##j -## k*##k- d = 2.0## *## ( i*##x +## j*##y +## k*##z)- t2 = t *## 2.0##- in SingleFrame- ( DoubleX3#- (l*##x +## d*##i +## t2 *## (z*##j -## y*##k))- (l*##y +## d*##j +## t2 *## (x*##k -## z*##i))- (l*##z +## d*##k +## t2 *## (y*##i -## x*##j))- )- {-# INLINE getRotScale #-}- getRotScale _ (SingleFrame (DoubleX3# 0.0## 0.0## 0.0##))- = QDouble (DoubleX4# 0.0## 0.0## 0.0## 0.0##)- getRotScale (SingleFrame (DoubleX3# 0.0## 0.0## 0.0##)) _- = case infty of D# x -> QDouble (DoubleX4# x x x x)- getRotScale a@(SingleFrame (DoubleX3# a1 a2 a3))- b@(SingleFrame (DoubleX3# b1 b2 b3))- = let ma = sqrtDouble# (a1*##a1 +## a2*##a2 +## a3*##a3)- mb = sqrtDouble# (b1*##b1 +## b2*##b2 +## b3*##b3)- d = a1*##b1 +## a2*##b2 +## a3*##b3- c = sqrtDouble# (ma*##mb +## d)- ma2 = ma *## sqrtDouble# 2.0##- r = 1.0## /## (ma2 *## c)- in case cross a b of- SingleFrame (DoubleX3# 0.0## 0.0## 0.0##) ->- if isTrue# (d >## 0.0##)- then QDouble (DoubleX4# 0.0## 0.0## 0.0## (sqrtDouble# (mb /## ma)))- -- Shall we move result from k to i component?- else QDouble (DoubleX4# 0.0## 0.0## (sqrtDouble# (mb /## ma)) 0.0##)- SingleFrame (DoubleX3# t1 t2 t3) -> QDouble- ( DoubleX4#- (t1 *## r)- (t2 *## r)- (t3 *## r)- (c /## ma2)- )- {-# INLINE axisRotation #-}- axisRotation (SingleFrame (DoubleX3# 0.0## 0.0## 0.0##)) _- = QDouble (DoubleX4# 0.0## 0.0## 0.0## 1.0##)- axisRotation (SingleFrame (DoubleX3# x y z)) (D# a)- = let c = cosDouble# (a *## 0.5##)- s = sinDouble# (a *## 0.5##)- /## sqrtDouble# (x*##x +## y*##y +## z*##z)- in QDouble- ( DoubleX4#- (x *## s)- (y *## s)- (z *## s)- c- )- {-# INLINE qArg #-}- qArg (QDouble (DoubleX4# x y z w))- = case atan2 (D# (sqrtDouble# (x*##x +## y*##y +## z*##z)))- (D# w) of- D# a -> D# (a *## 2.0##)- {-# INLINE fromMatrix33 #-}- fromMatrix33 m- = let d =- ( ix 0# m *## ( ix 4# m *## ix 8# m -## ix 5# m *## ix 7# m )- -## ix 1# m *## ( ix 3# m *## ix 8# m -## ix 5# m *## ix 6# m )- +## ix 2# m *## ( ix 3# m *## ix 7# m -## ix 4# m *## ix 6# m )- ) **## 0.33333333333333333333333333333333##- in QDouble- ( DoubleX4#- (sqrtDouble# (max# 0.0## (d +## ix 0# m -## ix 4# m -## ix 8# m )) *## sign# (ix 5# m -## ix 7# m) *## 0.5##)- (sqrtDouble# (max# 0.0## (d -## ix 0# m +## ix 4# m -## ix 8# m )) *## sign# (ix 6# m -## ix 2# m) *## 0.5##)- (sqrtDouble# (max# 0.0## (d -## ix 0# m -## ix 4# m +## ix 8# m )) *## sign# (ix 1# m -## ix 3# m) *## 0.5##)- (sqrtDouble# (max# 0.0## (d +## ix 0# m +## ix 4# m +## ix 8# m )) *## 0.5##)- )- {-# INLINE fromMatrix44 #-}- fromMatrix44 m- = let d =- ( ix 0# m *## ( ix 5# m *## ix 10# m -## ix 6# m *## ix 9# m )- -## ix 1# m *## ( ix 4# m *## ix 10# m -## ix 6# m *## ix 8# m )- +## ix 2# m *## ( ix 4# m *## ix 9# m -## ix 5# m *## ix 8# m )- ) **## 0.33333333333333333333333333333333##- c = 0.5## /## ix 15# m- in QDouble- ( DoubleX4#- (sqrtDouble# (max# 0.0## (d +## ix 0# m -## ix 5# m -## ix 10# m )) *## sign# (ix 6# m -## ix 9# m) *## c)- (sqrtDouble# (max# 0.0## (d -## ix 0# m +## ix 5# m -## ix 10# m )) *## sign# (ix 8# m -## ix 2# m) *## c)- (sqrtDouble# (max# 0.0## (d -## ix 0# m -## ix 5# m +## ix 10# m )) *## sign# (ix 1# m -## ix 4# m) *## c)- (sqrtDouble# (max# 0.0## (d +## ix 0# m +## ix 5# m +## ix 10# m )) *## c)- )- {-# INLINE toMatrix33 #-}- toMatrix33 (QDouble (DoubleX4# 0.0## 0.0## 0.0## w))- = let x = D# (w *## w)- f 0 = (# 3 :: Int , x #)- f k = (# k-1, 0 #)- in case gen# 9# f 0 of- (# _, m #) -> m -- diag (scalar (D# (w *## w)))- toMatrix33 (QDouble (DoubleX4# x' y' z' w')) =- let x = scalar (D# x')- y = scalar (D# y')- z = scalar (D# z')- w = scalar (D# w')- x2 = x * x- y2 = y * y- z2 = z * z- w2 = w * w- l2 = x2 + y2 + z2 + w2- in ST.runST $ do- df <- ST.newDataFrame- ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)- ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)- ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)- ST.writeDataFrameOff df 3 $ 2*(x*y - z*w)- ST.writeDataFrameOff df 4 $ l2 - 2*(z2 + x2)- ST.writeDataFrameOff df 5 $ 2*(y*z + x*w)- ST.writeDataFrameOff df 6 $ 2*(x*z + y*w)- ST.writeDataFrameOff df 7 $ 2*(y*z - x*w)- ST.writeDataFrameOff df 8 $ l2 - 2*(y2 + x2)- ST.unsafeFreezeDataFrame df- {-# INLINE toMatrix44 #-}- toMatrix44 (QDouble (DoubleX4# 0.0## 0.0## 0.0## w)) = ST.runST $ do- df <- ST.newDataFrame- ST.overDimOff_ (dims :: Dims '[4,4]) (\i -> ST.writeDataFrameOff df i 0) 0 1- let w2 = scalar (D# (w *## w))- ST.writeDataFrameOff df 0 w2- ST.writeDataFrameOff df 5 w2- ST.writeDataFrameOff df 10 w2- ST.writeDataFrameOff df 15 1- ST.unsafeFreezeDataFrame df- toMatrix44 (QDouble (DoubleX4# x' y' z' w')) =- let x = scalar (D# x')- y = scalar (D# y')- z = scalar (D# z')- w = scalar (D# w')- x2 = x * x- y2 = y * y- z2 = z * z- w2 = w * w- l2 = x2 + y2 + z2 + w2- in ST.runST $ do- df <- ST.newDataFrame- ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)- ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)- ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)- ST.writeDataFrameOff df 3 0- ST.writeDataFrameOff df 4 $ 2*(x*y - z*w)- ST.writeDataFrameOff df 5 $ l2 - 2*(z2 + x2)- ST.writeDataFrameOff df 6 $ 2*(y*z + x*w)- ST.writeDataFrameOff df 7 0- ST.writeDataFrameOff df 8 $ 2*(x*z + y*w)- ST.writeDataFrameOff df 9 $ 2*(y*z - x*w)- ST.writeDataFrameOff df 10 $ l2 - 2*(y2 + x2)- ST.writeDataFrameOff df 11 0- ST.writeDataFrameOff df 12 0- ST.writeDataFrameOff df 13 0- ST.writeDataFrameOff df 14 0- ST.writeDataFrameOff df 15 1- ST.unsafeFreezeDataFrame df--qdot :: QDouble -> Double#-qdot (QDouble (DoubleX4# x y z w)) = (x *## x) +##- (y *## y) +##- (z *## z) +##- (w *## w)-{-# INLINE qdot #-}--infty :: Double-infty = read "Infinity"--max# :: Double# -> Double# -> Double#-max# a b | isTrue# (a >## b) = a- | otherwise = b-{-# INLINE max# #-}--sign# :: Double# -> Double#-sign# a | isTrue# (a >## 0.0##) = 1.0##- | isTrue# (a <## 0.0##) = negateDouble# 1.0##- | otherwise = 0.0##-{-# INLINE sign# #-}--ix :: PrimArray Double a => Int# -> a -> Double#-ix i a = case ix# i a of D# r -> r-{-# INLINE ix #-}------------------------------------------------------------------------------- Num-----------------------------------------------------------------------------instance Num QDouble where- QDouble a + QDouble b- = QDouble (a + b)- {-# INLINE (+) #-}- QDouble a - QDouble b- = QDouble (a - b)- {-# INLINE (-) #-}- QDouble (DoubleX4# a1 a2 a3 a4) * QDouble (DoubleX4# b1 b2 b3 b4)- = QDouble- ( DoubleX4#- ((a4 *## b1) +##- (a1 *## b4) +##- (a2 *## b3) -##- (a3 *## b2)- )- ((a4 *## b2) -##- (a1 *## b3) +##- (a2 *## b4) +##- (a3 *## b1)- )- ((a4 *## b3) +##- (a1 *## b2) -##- (a2 *## b1) +##- (a3 *## b4)- )- ((a4 *## b4) -##- (a1 *## b1) -##- (a2 *## b2) -##- (a3 *## b3)- )- )- {-# INLINE (*) #-}- negate (QDouble a) = QDouble (negate a)- {-# INLINE negate #-}- abs q = QDouble (DoubleX4# 0.0## 0.0## 0.0## (sqrtDouble# (qdot q)))- {-# INLINE abs #-}- signum q@(QDouble (DoubleX4# x y z w))- = case qdot q of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## 0.0##)- qd -> case 1.0## /## sqrtDouble# qd of- s -> QDouble- ( DoubleX4#- (x *## s)- (y *## s)- (z *## s)- (w *## s)- )- {-# INLINE signum #-}- fromInteger n = case fromInteger n of- D# x -> QDouble (DoubleX4# 0.0## 0.0## 0.0## x)- {-# INLINE fromInteger #-}--------------------------------------------------------------------------------- Fractional-----------------------------------------------------------------------------instance Fractional QDouble where- {-# INLINE recip #-}- recip q@(QDouble (DoubleX4# x y z w)) = case -1.0## /## qdot q of- c -> QDouble- ( DoubleX4#- (x *## c)- (y *## c)- (z *## c)- (negateDouble# (w *## c))- )- {-# INLINE (/) #-}- a / b = a * recip b- {-# INLINE fromRational #-}- fromRational q = case fromRational q of- D# x -> QDouble (DoubleX4# 0.0## 0.0## 0.0## x)------------------------------------------------------------------------------- Doubleing-----------------------------------------------------------------------------instance Floating QDouble where- {-# INLINE pi #-}- pi = QDouble (DoubleX4# 0.0## 0.0## 0.0##- 3.141592653589793##)- {-# INLINE exp #-}- exp (QDouble (DoubleX4# x y z w))- = case (# (x *## x) +##- (y *## y) +##- (z *## z)- , expDouble# w- #) of- (# 0.0##, et #) -> QDouble (DoubleX4# 0.0## 0.0## 0.0## et)- (# mv2, et #) -> case sqrtDouble# mv2 of- mv -> case et *## sinDouble# mv- /## mv of- l -> QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (et *## cosDouble# mv)- )- {-# INLINE log #-}- log (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> if isTrue# (w >=## 0.0##)- then QDouble (DoubleX4# 0.0## 0.0## 0.0## (logDouble# w))- else QDouble (DoubleX4# 3.141592653589793## 0.0## 0.0##- (logDouble# (negateDouble# w)))- mv2 -> case (# sqrtDouble# (mv2 +## (w *## w))- , sqrtDouble# mv2- #) of- (# mq, mv #) -> case atan2 (D# mv) (D# w) / D# mv of- D# l -> QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (logDouble# mq)- )- {-# INLINE sqrt #-}- sqrt (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> if isTrue# (w >=## 0.0##)- then QDouble (DoubleX4# 0.0## 0.0## 0.0## (sqrtDouble# w))- else QDouble (DoubleX4# (sqrtDouble# (negateDouble# w)) 0.0## 0.0## 0.0##)- mv2 ->- let mq = sqrtDouble# (mv2 +## w *## w)- l2 = sqrtDouble# mq- tq = w /## (mq *## 2.0##)- sina = sqrtDouble# (0.5## -## tq) *## l2 /## sqrtDouble# mv2- in QDouble- ( DoubleX4#- (x *## sina)- (y *## sina)- (z *## sina)- (sqrtDouble# (0.5## +## tq) *## l2)- )- {-# INLINE sin #-}- sin (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## (sinDouble# w))- mv2 -> case sqrtDouble# mv2 of- mv -> case cosDouble# w *## sinhDouble# mv- /## mv of- l -> QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (sinDouble# w *## coshDouble# mv)- )- {-# INLINE cos #-}- cos (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## (cosDouble# w))- mv2 -> case sqrtDouble# mv2 of- mv -> case sinDouble# w *## sinhDouble# mv- /## negateDouble# mv of- l -> QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (cosDouble# w *## coshDouble# mv)- )- {-# INLINE tan #-}- tan (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## (tanDouble# w))- mv2 ->- let mv = sqrtDouble# mv2- chv = coshDouble# mv- shv = sinhDouble# mv- ct = cosDouble# w- st = sinDouble# w- cq = 1.0## /##- ( (ct *## ct *## chv *## chv)- +##- (st *## st *## shv *## shv)- )- l = chv *## shv *## cq- /## mv- in QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (ct *## st *## cq)- )- {-# INLINE sinh #-}- sinh (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## (sinhDouble# w))- mv2 -> case sqrtDouble# mv2 of- mv -> case coshDouble# w *## sinDouble# mv- /## mv of- l -> QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (sinhDouble# w *## cosDouble# mv)- )- {-# INLINE cosh #-}- cosh (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## (coshDouble# w))- mv2 -> case sqrtDouble# mv2 of- mv -> case sinhDouble# w *## sinDouble# mv- /## mv of- l -> QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (coshDouble# w *## cosDouble# mv)- )- {-# INLINE tanh #-}- tanh (QDouble (DoubleX4# x y z w))- = case (x *## x) +##- (y *## y) +##- (z *## z) of- 0.0## -> QDouble (DoubleX4# 0.0## 0.0## 0.0## (tanhDouble# w))- mv2 ->- let mv = sqrtDouble# mv2- cv = cosDouble# mv- sv = sinDouble# mv- cht = coshDouble# w- sht = sinhDouble# w- cq = 1.0## /##- ( (cht *## cht *## cv *## cv)- +##- (sht *## sht *## sv *## sv)- )- l = cv *## sv *## cq- /## mv- in QDouble- ( DoubleX4#- (x *## l)- (y *## l)- (z *## l)- (cht *## sht *## cq)- )- {-# INLINE asin #-}- asin q = -i * log (i*q + sqrt (1 - q*q))- where- i = case signum . im $ q of- 0 -> QDouble (DoubleX4# 1.0## 0.0## 0.0## 0.0##)- i' -> i'- {-# INLINE acos #-}- acos q = pi/2 - asin q- {-# INLINE atan #-}- atan q@(QDouble (DoubleX4# _ _ _ w))- = if square imq == 0- then QDouble (DoubleX4# 0.0## 0.0## 0.0## (atanDouble# w))- else i / 2 * log ( (i + q) / (i - q) )- where- i = signum imq- imq = im q- {-# INLINE asinh #-}- asinh q = log (q + sqrt (q*q + 1))- {-# INLINE acosh #-}- acosh q = log (q + sqrt (q*q - 1))- {-# INLINE atanh #-}- atanh q = 0.5 * log ((1+q)/(1-q))------------------------------------------------------------------------------- Eq-----------------------------------------------------------------------------instance Eq QDouble where- {-# INLINE (==) #-}- QDouble a == QDouble b = a == b- {-# INLINE (/=) #-}- QDouble a /= QDouble b = a /= b--------------------------------------------------------------------------------- Show-----------------------------------------------------------------------------instance Show QDouble where- show (QDouble (DoubleX4# x y z w)) =- show (D# w) ++ ss x ++ "i"- ++ ss y ++ "j"- ++ ss z ++ "k"- where- ss a# = case D# a# of- a -> if a >= 0 then " + " ++ show a- else " - " ++ show (negate a)
− src/Numeric/Quaternion/QFloat.hs
@@ -1,579 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE UnboxedTuples #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Numeric.Quaternion.QFloat- ( QFloat, Quater (..)- ) where--import Data.Coerce (coerce)-import GHC.Exts--import qualified Control.Monad.ST as ST-import Numeric.DataFrame.Internal.Array.Class-import Numeric.DataFrame.Internal.Array.Family.FloatX3-import Numeric.DataFrame.Internal.Array.Family.FloatX4-import qualified Numeric.DataFrame.ST as ST-import Numeric.DataFrame.Type-import Numeric.Dimensions-import qualified Numeric.Dimensions.Fold as ST-import Numeric.PrimBytes (PrimBytes)-import Numeric.Quaternion.Class-import Numeric.Scalar-import Numeric.Vector---type QFloat = Quater Float--deriving instance PrimBytes (Quater Float)-deriving instance PrimArray Float (Quater Float)--instance Quaternion Float where- newtype Quater Float = QFloat FloatX4- {-# INLINE packQ #-}- packQ (F# x) (F# y) (F# z) (F# w) = QFloat (FloatX4# x y z w)- {-# INLINE unpackQ #-}- unpackQ (QFloat (FloatX4# x y z w)) = (F# x, F# y, F# z, F# w)- {-# INLINE fromVecNum #-}- fromVecNum (SingleFrame (FloatX3# x y z)) (F# w) = QFloat (FloatX4# x y z w)- {-# INLINE fromVec4 #-}- fromVec4 = coerce- {-# INLINE toVec4 #-}- toVec4 = coerce- {-# INLINE square #-}- square q = F# (qdot q)- {-# INLINE im #-}- im (QFloat (FloatX4# x y z _)) = QFloat (FloatX4# x y z 0.0#)- {-# INLINE re #-}- re (QFloat (FloatX4# _ _ _ w)) = QFloat (FloatX4# 0.0# 0.0# 0.0# w)- {-# INLINE imVec #-}- imVec (QFloat (FloatX4# x y z _)) = SingleFrame (FloatX3# x y z)- {-# INLINE taker #-}- taker (QFloat (FloatX4# _ _ _ w)) = F# w- {-# INLINE takei #-}- takei (QFloat (FloatX4# x _ _ _)) = F# x- {-# INLINE takej #-}- takej (QFloat (FloatX4# _ y _ _)) = F# y- {-# INLINE takek #-}- takek (QFloat (FloatX4# _ _ z _)) = F# z- {-# INLINE conjugate #-}- conjugate (QFloat (FloatX4# x y z w)) = QFloat (FloatX4#- (negateFloat# x)- (negateFloat# y)- (negateFloat# z) w)- {-# INLINE rotScale #-}- rotScale (QFloat (FloatX4# i j k t))- (SingleFrame (FloatX3# x y z))- = let l = t*%t -% i*%i -% j*%j -% k*%k- d = 2.0# *% ( i*%x +% j*%y +% k*%z)- t2 = t *% 2.0#- in SingleFrame- ( FloatX3#- (l*%x +% d*%i +% t2 *% (z*%j -% y*%k))- (l*%y +% d*%j +% t2 *% (x*%k -% z*%i))- (l*%z +% d*%k +% t2 *% (y*%i -% x*%j))- )- {-# INLINE getRotScale #-}- getRotScale _ (SingleFrame (FloatX3# 0.0# 0.0# 0.0#))- = QFloat (FloatX4# 0.0# 0.0# 0.0# 0.0#)- getRotScale (SingleFrame (FloatX3# 0.0# 0.0# 0.0#)) _- = case infty of F# x -> QFloat (FloatX4# x x x x)- getRotScale a@(SingleFrame (FloatX3# a1 a2 a3))- b@(SingleFrame (FloatX3# b1 b2 b3))- = let ma = sqrtFloat# (a1*%a1 +% a2*%a2 +% a3*%a3)- mb = sqrtFloat# (b1*%b1 +% b2*%b2 +% b3*%b3)- d = a1*%b1 +% a2*%b2 +% a3*%b3- c = sqrtFloat# (ma*%mb +% d)- ma2 = ma *% sqrtFloat# 2.0#- r = 1.0# /% (ma2 *% c)- in case cross a b of- SingleFrame (FloatX3# 0.0# 0.0# 0.0#) ->- if isTrue# (gtFloat# d 0.0#)- then QFloat (FloatX4# 0.0# 0.0# 0.0# (sqrtFloat# (mb /% ma)))- -- Shall we move result from k to i component?- else QFloat (FloatX4# 0.0# 0.0# (sqrtFloat# (mb /% ma)) 0.0#)- SingleFrame (FloatX3# t1 t2 t3) -> QFloat- ( FloatX4#- (t1 *% r)- (t2 *% r)- (t3 *% r)- (c /% ma2)- )- {-# INLINE axisRotation #-}- axisRotation (SingleFrame (FloatX3# 0.0# 0.0# 0.0#)) _- = QFloat (FloatX4# 0.0# 0.0# 0.0# 1.0#)- axisRotation (SingleFrame (FloatX3# x y z)) (F# a)- = let c = cosFloat# (a *% 0.5#)- s = sinFloat# (a *% 0.5#)- /% sqrtFloat# (x*%x +% y*%y +% z*%z)- in QFloat- ( FloatX4#- (x *% s)- (y *% s)- (z *% s)- c- )- {-# INLINE qArg #-}- qArg (QFloat (FloatX4# x y z w))- = case atan2 (F# (sqrtFloat# (x*%x +% y*%y +% z*%z)))- (F# w) of- F# a -> F# (a *% 2.0#)- {-# INLINE fromMatrix33 #-}- fromMatrix33 m- = let d = powerFloat#- ( ix 0# m *% ( ix 4# m *% ix 8# m -% ix 5# m *% ix 7# m )- -% ix 1# m *% ( ix 3# m *% ix 8# m -% ix 5# m *% ix 6# m )- +% ix 2# m *% ( ix 3# m *% ix 7# m -% ix 4# m *% ix 6# m )- ) 0.33333333333333333333333333333333#- in QFloat- ( FloatX4#- (sqrtFloat# (max# 0.0# (d +% ix 0# m -% ix 4# m -% ix 8# m )) *% sign# (ix 5# m -% ix 7# m) *% 0.5#)- (sqrtFloat# (max# 0.0# (d -% ix 0# m +% ix 4# m -% ix 8# m )) *% sign# (ix 6# m -% ix 2# m) *% 0.5#)- (sqrtFloat# (max# 0.0# (d -% ix 0# m -% ix 4# m +% ix 8# m )) *% sign# (ix 1# m -% ix 3# m) *% 0.5#)- (sqrtFloat# (max# 0.0# (d +% ix 0# m +% ix 4# m +% ix 8# m )) *% 0.5#)- )- {-# INLINE fromMatrix44 #-}- fromMatrix44 m- = let d = powerFloat#- ( ix 0# m *% ( ix 5# m *% ix 10# m -% ix 6# m *% ix 9# m )- -% ix 1# m *% ( ix 4# m *% ix 10# m -% ix 6# m *% ix 8# m )- +% ix 2# m *% ( ix 4# m *% ix 9# m -% ix 5# m *% ix 8# m )- ) 0.33333333333333333333333333333333#- c = 0.5# /% ix 15# m- in QFloat- ( FloatX4#- (sqrtFloat# (max# 0.0# (d +% ix 0# m -% ix 5# m -% ix 10# m )) *% sign# (ix 6# m -% ix 9# m) *% c)- (sqrtFloat# (max# 0.0# (d -% ix 0# m +% ix 5# m -% ix 10# m )) *% sign# (ix 8# m -% ix 2# m) *% c)- (sqrtFloat# (max# 0.0# (d -% ix 0# m -% ix 5# m +% ix 10# m )) *% sign# (ix 1# m -% ix 4# m) *% c)- (sqrtFloat# (max# 0.0# (d +% ix 0# m +% ix 5# m +% ix 10# m )) *% c)- )- {-# INLINE toMatrix33 #-}- toMatrix33 (QFloat (FloatX4# 0.0# 0.0# 0.0# w))- = let x = F# (w *% w)- f 0 = (# 3 :: Int , x #)- f k = (# k-1, 0 #)- in case gen# 9# f 0 of- (# _, m #) -> m -- diag (scalar (F# (w *% w)))- toMatrix33 (QFloat (FloatX4# x' y' z' w')) =- let x = scalar (F# x')- y = scalar (F# y')- z = scalar (F# z')- w = scalar (F# w')- x2 = x * x- y2 = y * y- z2 = z * z- w2 = w * w- l2 = x2 + y2 + z2 + w2- in ST.runST $ do- df <- ST.newDataFrame- ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)- ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)- ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)- ST.writeDataFrameOff df 3 $ 2*(x*y - z*w)- ST.writeDataFrameOff df 4 $ l2 - 2*(z2 + x2)- ST.writeDataFrameOff df 5 $ 2*(y*z + x*w)- ST.writeDataFrameOff df 6 $ 2*(x*z + y*w)- ST.writeDataFrameOff df 7 $ 2*(y*z - x*w)- ST.writeDataFrameOff df 8 $ l2 - 2*(y2 + x2)- ST.unsafeFreezeDataFrame df- {-# INLINE toMatrix44 #-}- toMatrix44 (QFloat (FloatX4# 0.0# 0.0# 0.0# w)) = ST.runST $ do- df <- ST.newDataFrame- ST.overDimOff_ (dims :: Dims '[4,4]) (\i -> ST.writeDataFrameOff df i 0) 0 1- let w2 = scalar (F# (w *% w))- ST.writeDataFrameOff df 0 w2- ST.writeDataFrameOff df 5 w2- ST.writeDataFrameOff df 10 w2- ST.writeDataFrameOff df 15 1- ST.unsafeFreezeDataFrame df- toMatrix44 (QFloat (FloatX4# x' y' z' w')) =- let x = scalar (F# x')- y = scalar (F# y')- z = scalar (F# z')- w = scalar (F# w')- x2 = x * x- y2 = y * y- z2 = z * z- w2 = w * w- l2 = x2 + y2 + z2 + w2- in ST.runST $ do- df <- ST.newDataFrame- ST.writeDataFrameOff df 0 $ l2 - 2*(z2 + y2)- ST.writeDataFrameOff df 1 $ 2*(x*y + z*w)- ST.writeDataFrameOff df 2 $ 2*(x*z - y*w)- ST.writeDataFrameOff df 3 0- ST.writeDataFrameOff df 4 $ 2*(x*y - z*w)- ST.writeDataFrameOff df 5 $ l2 - 2*(z2 + x2)- ST.writeDataFrameOff df 6 $ 2*(y*z + x*w)- ST.writeDataFrameOff df 7 0- ST.writeDataFrameOff df 8 $ 2*(x*z + y*w)- ST.writeDataFrameOff df 9 $ 2*(y*z - x*w)- ST.writeDataFrameOff df 10 $ l2 - 2*(y2 + x2)- ST.writeDataFrameOff df 11 0- ST.writeDataFrameOff df 12 0- ST.writeDataFrameOff df 13 0- ST.writeDataFrameOff df 14 0- ST.writeDataFrameOff df 15 0- ST.unsafeFreezeDataFrame df--qdot :: QFloat -> Float#-qdot (QFloat (FloatX4# x y z w)) = (x *% x) +%- (y *% y) +%- (z *% z) +%- (w *% w)-{-# INLINE qdot #-}--(*%) :: Float# -> Float# -> Float#-(*%) = timesFloat#-{-# INLINE (*%) #-}-infixl 7 *%--(-%) :: Float# -> Float# -> Float#-(-%) = minusFloat#-{-# INLINE (-%) #-}-infixl 6 -%--(+%) :: Float# -> Float# -> Float#-(+%) = plusFloat#-{-# INLINE (+%) #-}-infixl 6 +%--(/%) :: Float# -> Float# -> Float#-(/%) = divideFloat#-{-# INLINE (/%) #-}-infixl 7 /%--infty :: Float-infty = read "Infinity"--max# :: Float# -> Float# -> Float#-max# a b | isTrue# (gtFloat# a b) = a- | otherwise = b-{-# INLINE max# #-}--sign# :: Float# -> Float#-sign# a | isTrue# (gtFloat# a 0.0#) = 1.0#- | isTrue# (ltFloat# a 0.0#) = negateFloat# 1.0#- | otherwise = 0.0#-{-# INLINE sign# #-}--ix :: PrimArray Float a => Int# -> a -> Float#-ix i a = case ix# i a of F# r -> r-{-# INLINE ix #-}------------------------------------------------------------------------------- Num-----------------------------------------------------------------------------instance Num QFloat where- QFloat a + QFloat b- = QFloat (a + b)- {-# INLINE (+) #-}- QFloat a - QFloat b- = QFloat (a - b)- {-# INLINE (-) #-}- QFloat (FloatX4# a1 a2 a3 a4) * QFloat (FloatX4# b1 b2 b3 b4)- = QFloat- ( FloatX4#- ((a4 *% b1) +%- (a1 *% b4) +%- (a2 *% b3) -%- (a3 *% b2)- )- ((a4 *% b2) -%- (a1 *% b3) +%- (a2 *% b4) +%- (a3 *% b1)- )- ((a4 *% b3) +%- (a1 *% b2) -%- (a2 *% b1) +%- (a3 *% b4)- )- ((a4 *% b4) -%- (a1 *% b1) -%- (a2 *% b2) -%- (a3 *% b3)- )- )- {-# INLINE (*) #-}- negate (QFloat a) = QFloat (negate a)- {-# INLINE negate #-}- abs q = QFloat (FloatX4# 0.0# 0.0# 0.0# (sqrtFloat# (qdot q)))- {-# INLINE abs #-}- signum q@(QFloat (FloatX4# x y z w))- = case qdot q of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# 0.0#)- qd -> case 1.0# /% sqrtFloat# qd of- s -> QFloat- ( FloatX4#- (x *% s)- (y *% s)- (z *% s)- (w *% s)- )- {-# INLINE signum #-}- fromInteger n = case fromInteger n of- F# x -> QFloat (FloatX4# 0.0# 0.0# 0.0# x)- {-# INLINE fromInteger #-}--------------------------------------------------------------------------------- Fractional-----------------------------------------------------------------------------instance Fractional QFloat where- {-# INLINE recip #-}- recip q@(QFloat (FloatX4# x y z w)) = case -1.0# /% qdot q of- c -> QFloat- ( FloatX4#- (x *% c)- (y *% c)- (z *% c)- (negateFloat# (w *% c))- )- {-# INLINE (/) #-}- a / b = a * recip b- {-# INLINE fromRational #-}- fromRational q = case fromRational q of- F# x -> QFloat (FloatX4# 0.0# 0.0# 0.0# x)------------------------------------------------------------------------------- Floating-----------------------------------------------------------------------------instance Floating QFloat where- {-# INLINE pi #-}- pi = QFloat (FloatX4# 0.0# 0.0# 0.0#- 3.141592653589793#)- {-# INLINE exp #-}- exp (QFloat (FloatX4# x y z w))- = case (# (x *% x) +%- (y *% y) +%- (z *% z)- , expFloat# w- #) of- (# 0.0#, et #) -> QFloat (FloatX4# 0.0# 0.0# 0.0# et)- (# mv2, et #) -> case sqrtFloat# mv2 of- mv -> case et *% sinFloat# mv- /% mv of- l -> QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (et *% cosFloat# mv)- )- {-# INLINE log #-}- log (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> if isTrue# (w `geFloat#` 0.0#)- then QFloat (FloatX4# 0.0# 0.0# 0.0# (logFloat# w))- else QFloat (FloatX4# 3.141592653589793# 0.0# 0.0#- (logFloat# (negateFloat# w)))- mv2 -> case (# sqrtFloat# (mv2 +% (w *% w))- , sqrtFloat# mv2- #) of- (# mq, mv #) -> case atan2 (F# mv) (F# w) / F# mv of- F# l -> QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (logFloat# mq)- )- {-# INLINE sqrt #-}- sqrt (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> if isTrue# (w `geFloat#` 0.0#)- then QFloat (FloatX4# 0.0# 0.0# 0.0# (sqrtFloat# w))- else QFloat (FloatX4# (sqrtFloat# (negateFloat# w)) 0.0# 0.0# 0.0#)- mv2 ->- let mq = sqrtFloat# (mv2 +% w *% w)- l2 = sqrtFloat# mq- tq = w /% (mq *% 2.0#)- sina = sqrtFloat# (0.5# -% tq) *% l2 /% sqrtFloat# mv2- in QFloat- ( FloatX4#- (x *% sina)- (y *% sina)- (z *% sina)- (sqrtFloat# (0.5# +% tq) *% l2)- )- {-# INLINE sin #-}- sin (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# (sinFloat# w))- mv2 -> case sqrtFloat# mv2 of- mv -> case cosFloat# w *% sinhFloat# mv- /% mv of- l -> QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (sinFloat# w *% coshFloat# mv)- )- {-# INLINE cos #-}- cos (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# (cosFloat# w))- mv2 -> case sqrtFloat# mv2 of- mv -> case sinFloat# w *% sinhFloat# mv- /% negateFloat# mv of- l -> QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (cosFloat# w *% coshFloat# mv)- )- {-# INLINE tan #-}- tan (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# (tanFloat# w))- mv2 ->- let mv = sqrtFloat# mv2- chv = coshFloat# mv- shv = sinhFloat# mv- ct = cosFloat# w- st = sinFloat# w- cq = 1.0# /%- ( (ct *% ct *% chv *% chv)- +%- (st *% st *% shv *% shv)- )- l = chv *% shv *% cq- /% mv- in QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (ct *% st *% cq)- )- {-# INLINE sinh #-}- sinh (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# (sinhFloat# w))- mv2 -> case sqrtFloat# mv2 of- mv -> case coshFloat# w *% sinFloat# mv- /% mv of- l -> QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (sinhFloat# w *% cosFloat# mv)- )- {-# INLINE cosh #-}- cosh (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# (coshFloat# w))- mv2 -> case sqrtFloat# mv2 of- mv -> case sinhFloat# w *% sinFloat# mv- /% mv of- l -> QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (coshFloat# w *% cosFloat# mv)- )- {-# INLINE tanh #-}- tanh (QFloat (FloatX4# x y z w))- = case (x *% x) +%- (y *% y) +%- (z *% z) of- 0.0# -> QFloat (FloatX4# 0.0# 0.0# 0.0# (tanhFloat# w))- mv2 ->- let mv = sqrtFloat# mv2- cv = cosFloat# mv- sv = sinFloat# mv- cht = coshFloat# w- sht = sinhFloat# w- cq = 1.0# /%- ( (cht *% cht *% cv *% cv)- +%- (sht *% sht *% sv *% sv)- )- l = cv *% sv *% cq- /% mv- in QFloat- ( FloatX4#- (x *% l)- (y *% l)- (z *% l)- (cht *% sht *% cq)- )- {-# INLINE asin #-}- asin q = -i * log (i*q + sqrt (1 - q*q))- where- i = case signum . im $ q of- 0 -> QFloat (FloatX4# 1.0# 0.0# 0.0# 0.0#)- i' -> i'- {-# INLINE acos #-}- acos q = pi/2 - asin q- {-# INLINE atan #-}- atan q@(QFloat (FloatX4# _ _ _ w))- = if square imq == 0- then QFloat (FloatX4# 0.0# 0.0# 0.0# (atanFloat# w))- else i / 2 * log ( (i + q) / (i - q) )- where- i = signum imq- imq = im q- {-# INLINE asinh #-}- asinh q = log (q + sqrt (q*q + 1))- {-# INLINE acosh #-}- acosh q = log (q + sqrt (q*q - 1))- {-# INLINE atanh #-}- atanh q = 0.5 * log ((1+q)/(1-q))------------------------------------------------------------------------------- Eq-----------------------------------------------------------------------------instance Eq QFloat where- {-# INLINE (==) #-}- QFloat a == QFloat b = a == b- {-# INLINE (/=) #-}- QFloat a /= QFloat b = a /= b--------------------------------------------------------------------------------- Show-----------------------------------------------------------------------------instance Show QFloat where- show (QFloat (FloatX4# x y z w)) =- show (F# w) ++ ss x ++ "i"- ++ ss y ++ "j"- ++ ss z ++ "k"- where- ss a# = case F# a# of- a -> if a >= 0 then " + " ++ show a- else " - " ++ show (negate a)
src/Numeric/Scalar.hs view
@@ -1,41 +1,8 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MonoLocalBinds #-} -- | Scalar is an alias to zero-dimensional DataFrame module Numeric.Scalar ( Scalar, unScalar, scalar, fromScalar , Scf, Scd, Sci, Scw ) where --import GHC.Base (unsafeCoerce#)-import Numeric.DataFrame.Family (DataFrame)-import Numeric.DataFrame.SubSpace (SubSpace (ewgen))-import Numeric.Dim (Nat)---- | Alias for zero-dimensional DataFrame-type Scalar t = DataFrame t ('[] :: [Nat])-type Scf = Scalar Float-type Scd = Scalar Double-type Sci = Scalar Int-type Scw = Scalar Word---- | Convert scalar back to ordinary type-unScalar :: Scalar t -> t--- rely on that Scalar is just two times newtype alias to t-unScalar = unsafeCoerce#-{-# INLINE unScalar #-}---- | Convert any type to scalar wrapper-scalar :: t -> Scalar t--- rely on that Scalar is just two times newtype alias to t-scalar = unsafeCoerce#-{-# INLINE scalar #-}---- | Broadcast scalar value onto a whole data frame-fromScalar :: SubSpace t '[] ds ds- => Scalar t -> DataFrame t ds-fromScalar = ewgen-{-# INLINE fromScalar #-}+import Numeric.DataFrame.Internal.Backend ()+import Numeric.Scalar.Internal
+ src/Numeric/Scalar/Internal.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE PatternSynonyms #-}+-- | Scalar is an alias to zero-dimensional DataFrame+module Numeric.Scalar.Internal+ ( Scalar, unScalar, scalar, fromScalar+ , Scf, Scd, Sci, Scw+ , pattern S+ ) where+++import Data.Type.Lits (Nat)+import GHC.Base (unsafeCoerce#)+import Numeric.DataFrame.SubSpace (SubSpace (ewgen))+import Numeric.DataFrame.Type (DataFrame, pattern S)++-- | Alias for zero-dimensional DataFrame+type Scalar t = DataFrame t ('[] :: [Nat])+type Scf = Scalar Float+type Scd = Scalar Double+type Sci = Scalar Int+type Scw = Scalar Word++-- | Convert scalar back to ordinary type+unScalar :: Scalar t -> t+-- rely on that Scalar is just two times newtype alias to t+unScalar = unsafeCoerce#+{-# INLINE unScalar #-}++-- | Convert any type to scalar wrapper+scalar :: t -> Scalar t+-- rely on that Scalar is just two times newtype alias to t+scalar = unsafeCoerce#+{-# INLINE scalar #-}++-- | Broadcast scalar value onto a whole data frame+fromScalar :: SubSpace t ds '[] ds+ => Scalar t -> DataFrame t ds+fromScalar = ewgen+{-# INLINE fromScalar #-}
− src/Numeric/Semigroup.hs
@@ -1,219 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--------------------------------------------------------------------------------- |--- Module : Numeric.Semigroup--- Copyright : (c) Artem Chirkin--- License : BSD3------ Maintainer : chirkin@arch.ethz.ch------ Re-export most of "Data.Semigroup" with a few changes--- and new definitions.------ The main initiative behind this module is to provide more strict--- alternatives to widely used semigroups.--- For example, 'Data.Semigroup.Option' has lazy @(\<\>)@ implementation,--- which causes memory leaks in large foldMaps.----------------------------------------------------------------------------------module Numeric.Semigroup- ( Semigroup(..)- , stimesMonoid- , stimesIdempotent- , stimesIdempotentMonoid- , mtimesDefault- , foldMap'- -- * Semigroups- , Min(..)- , Max(..)- , First(..)- , Last(..)- , WrappedMonoid(..)- -- * Re-exported monoids from Data.Monoid- , Monoid(..)- , Dual(..)- , Endo(..)- , All(..)- , Any(..)- , Sum(..)- , Product(..)- -- * A better monoid for Maybe- , Option (..)- , option, fromOption, toOption- -- * Difference lists of a semigroup- , diff- , cycle1- -- * ArgMin, ArgMax- , Arg(..)- , ArgMin- , ArgMax- , MinMax (..)- , minMax, mmDiff, mmAvg- ) where--import Data.Semigroup hiding (Option (..), option)-import Data.Foldable (foldl')-import Data.Data-import Control.Applicative-import Control.Monad.Fix-import GHC.Generics---- | 'Option' is effectively 'Maybe' with a better instance of--- 'Monoid', built off of an underlying 'Semigroup' instead of an--- underlying 'Monoid'.------ This version of 'Option' data type is more strict than the one from--- "Data.Semigroup".-newtype Option a = Option { getOption :: Maybe a }- deriving ( Eq, Ord, Show, Read, Data, Typeable, Generic, Generic1- , Functor, Alternative, Applicative, Monad, MonadFix)---- | Fold an 'Option' case-wise, just like 'maybe'.--- Eagerly evaluates the value before returning!-option :: b -> (a -> b) -> Option a -> b-option !b _ (Option Nothing) = b-option _ f (Option (Just !a)) = f a---- | Get value from 'Option' with default value.--- Eagerly evaluates the value before returning!-fromOption :: a -> Option a -> a-fromOption !a (Option Nothing) = a-fromOption _ (Option (Just !a)) = a---- | Wrap a value into 'Option' container.--- Eagerly evaluates the value before wrapping!-toOption :: a -> Option a-toOption !a = Option (Just a)---instance Foldable Option where- foldMap _ (Option Nothing) = mempty- foldMap f (Option (Just !a)) = f a--instance Traversable Option where- traverse _ (Option Nothing) = pure (Option Nothing)- traverse f (Option (Just !a)) = (\ !b -> Option (Just b)) <$> f a--instance Semigroup a => Semigroup (Option a) where- Option Nothing <> Option Nothing = Option Nothing- Option Nothing <> Option (Just !a) = Option (Just a)- Option (Just !a) <> Option Nothing = Option (Just a)- Option (Just !a) <> Option (Just !b) = Option (Just $! a <> b)-- stimes _ (Option Nothing) = Option Nothing- stimes n (Option (Just a)) = case compare n 0 of- LT -> errorWithoutStackTrace "stimes: Option, negative multiplier"- EQ -> Option Nothing- GT -> Option (Just $! stimes n a)--instance Semigroup a => Monoid (Option a) where- mappend = (<>)- mempty = Option Nothing------ | Evaluate minimum and maximum at the same time.--- Arithmetics and semigroup operations are eager,--- functorial operations are lazy.------ This data type is especially useful for calculating bounds--- of foldable containers with numeric data using @foldMap minMax@.-data MinMax a = MinMax a a- deriving (Eq, Read, Show, Data, Typeable, Generic, Generic1)--minMax :: a -> MinMax a-minMax !a = MinMax a a--mmDiff :: Num a => MinMax a -> a-mmDiff (MinMax !x !y) = y - x--mmAvg :: Fractional a => MinMax a -> a-mmAvg (MinMax !x !y) = 0.5 * (x+y)--strictMinMax :: a -> a -> MinMax a-strictMinMax !a !b = MinMax a b--instance Ord a => Semigroup (MinMax a) where- (MinMax !x1 !y1) <> (MinMax !x2 !y2) = strictMinMax (min x1 x2) (max y1 y2)-- -- 'MinMax' is idempotent.- -- Also we don't care if @n@ is not positive.- stimes _ (MinMax !x !y) = MinMax x y----instance (Ord a, Bounded a) => Monoid (MinMax a) where- -- | Empty instance of minmax is an invalid value @min >= max@.- -- However, this gives a good monoid append behavior.- mempty = strictMinMax maxBound minBound- mappend = (<>)---instance Functor MinMax where- fmap f (MinMax a b) = MinMax (f a) (f b)--instance Applicative MinMax where- pure a = MinMax a a- MinMax f g <*> MinMax a b = MinMax (f a) (g b)--instance Monad MinMax where- return = pure- MinMax a b >>= m = case (m a, m b) of- (MinMax x _, MinMax _ y) -> MinMax x y--instance MonadFix MinMax where- mfix mf = let MinMax x _ = mf x- MinMax _ y = mf y- in MinMax x y--instance Bounded a => Bounded (MinMax a) where- minBound = strictMinMax minBound minBound- maxBound = strictMinMax maxBound maxBound---- | MinMax checks whether bounds overlap.------ * Strict inequality means that intervals do not overlap.--- * Non-strict inequality means non-strict inequality in both constructor arguments.--- * `EQ` means intervals overlap-instance Ord a => Ord (MinMax a) where- MinMax _ amax < MinMax bmin _ = amax < bmin- MinMax amin _ > MinMax _ bmax = amin > bmax- MinMax amin amax <= MinMax bmin bmax = amin <= bmin && amax <= bmax- MinMax amin amax >= MinMax bmin bmax = amin >= bmin && amax >= bmax- -- | A contraversal decision was made here: implementing `compare` operation.- -- `compare` returns GT or LT only if bounds do not overlap and returns EQ otherwise.- compare (MinMax amin amax) (MinMax bmin bmax)- | amin > bmax = GT- | bmin > amax = LT- | otherwise = EQ- min (MinMax amin amax) (MinMax bmin bmax) = strictMinMax (min amin bmin) (min amax bmax)- max (MinMax amin amax) (MinMax bmin bmax) = strictMinMax (max amin bmin) (max amax bmax)--instance (Num a, Ord a) => Num (MinMax a) where- (MinMax !x1 !y1) + (MinMax !x2 !y2) = strictMinMax (x1+x2) (y1+y2)- (MinMax !x1 !y1) - (MinMax !x2 !y2) = strictMinMax (x1-y2) (y1-x2)- (MinMax !x1 !y1) * (MinMax !x2 !y2) = strictMinMax (x1*x2) (y1*y2)- abs (MinMax !x !y) = case (abs x, abs y) of- (!ax, !ay) -> strictMinMax (min ax ay) (max ax ay)- negate (MinMax !x !y) = strictMinMax (negate y) (negate x)- signum (MinMax !x !y) = strictMinMax (signum x) (signum y)- fromInteger = minMax . fromInteger----- | Map each element of the structure to a monoid,--- and combine the results.------ This function differs from @Data.Foldable.foldMap@ in that uses @foldl'@--- instead of @foldr@ inside.--- This makes this function suitable for Monoids with strict `mappend` operation.--- For example,------ > foldMap' Sum $ take 1000000000 ([1..] :: [Int])------ runs in constant memory, whereas normal @foldMap@ would cause a memory leak there.-foldMap' :: (Foldable t, Monoid m) => (a -> m) -> t a -> m-foldMap' f = foldl' (flip $ mappend . f) mempty-{-# INLINE foldMap' #-}
src/Numeric/Vector.hs view
@@ -1,184 +1,18 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PolyKinds #-} -- | Vector is an alias to a DataFrame with order 1. module Numeric.Vector- ( -- * Type aliases+ ( -- * Type aliases Vector , Vec2f, Vec3f, Vec4f, Vec2d, Vec3d, Vec4d , Vec2i, Vec3i, Vec4i, Vec2w, Vec3w, Vec4w+ -- * Vector constructors+ , Vector2 (..), Vector3 (..), Vector4 (..)+ , DataFrame(Vec2, Vec3, Vec4) -- * Common operations , (.*.), dot, (·) , normL1, normL2, normLPInf, normLNInf, normLP , normalized- , vec2, vec3, vec4 , det2, cross, (×)- , unpackV2, unpackV3, unpackV4 ) where -import Numeric.DataFrame.SubSpace-import Numeric.DataFrame.Type-import Numeric.Scalar------------------------------------------------------------------------------------- * Vector type-----------------------------------------------------------------------------------type Vector (t :: l) (n :: k) = DataFrame t '[n]--type Vec2f = Vector Float 2-type Vec3f = Vector Float 3-type Vec4f = Vector Float 4-type Vec2d = Vector Double 2-type Vec3d = Vector Double 3-type Vec4d = Vector Double 4-type Vec2i = Vector Int 2-type Vec3i = Vector Int 3-type Vec4i = Vector Int 4-type Vec2w = Vector Word 2-type Vec3w = Vector Word 3-type Vec4w = Vector Word 4----- | Scalar product -- sum of Vecs' components products,--- propagated into whole Vec-(.*.) :: ( Num t- , Num (Vector t n)- , SubSpace t '[] '[n] '[n]- )- => Vector t n -> Vector t n -> Vector t n-(.*.) a b = fromScalar . ewfoldl (+) 0 $ a * b-infixl 7 .*.---- | Scalar product -- sum of Vecs' components products -- a scalar-dot :: ( Num t- , Num (Vector t n)- , SubSpace t '[] '[n] '[n]- )- => Vector t n -> Vector t n -> Scalar t-dot a b = ewfoldl (+) 0 $ a * b---- | Dot product of two vectors-infixl 7 ·-(·) :: ( Num t- , Num (Vector t n)- , SubSpace t '[] '[n] '[n]- )- => Vector t n -> Vector t n -> Scalar t-(·) = dot-{-# INLINE (·) #-}----- | Sum of absolute values-normL1 :: ( Num t, SubSpace t '[] '[n] '[n] )- => Vector t n -> Scalar t-normL1 = ewfoldr (\a -> (abs a +)) 0---- | hypot function (square root of squares)-normL2 :: ( Floating t , SubSpace t '[] '[n] '[n] )- => Vector t n -> Scalar t-normL2 = sqrt . ewfoldr (\a -> (a*a +)) 0---- | Normalize vector w.r.t. Euclidean metric (L2).-normalized :: ( Floating t , Fractional (Vector t n), SubSpace t '[] '[n] '[n] )- => Vector t n -> Vector t n-normalized v = v / n- where- n = fromScalar . sqrt $ ewfoldr (\a -> (a*a +)) 0 v---- | Maximum of absolute values-normLPInf :: ( Ord t, Num t , SubSpace t '[] '[n] '[n] )- => Vector t n -> Scalar t-normLPInf = ewfoldr (max . abs) 0---- | Minimum of absolute values-normLNInf :: ( Ord t, Num t , SubSpace t '[] '[n] '[n] )- => Vector t n -> Scalar t-normLNInf x = ewfoldr (min . abs) (abs $ x ! Idx 1 :* U) x---- | Norm in Lp space-normLP :: ( Floating t , SubSpace t '[] '[n] '[n] )- => Int -> Vector t n -> Scalar t-normLP i' = (**ri) . ewfoldr (\a -> (a**i +)) 0- where- i = fromIntegral i'- ri = recip i-{-# INLINE [2] normLP #-}-{-# RULES-"normLP/L1" normLP 1 = normL1-"normLP/L2" normLP 2 = normL2- #-}---- | Compose a 2D vector-vec2 :: SubSpace t '[] '[2] '[2] => t -> t -> Vector t 2-vec2 a b = iwgen f- where- f (1 :* U) = scalar a- f _ = scalar b---- | Take a determinant of a matrix composed from two 2D vectors.--- Like a cross product in 2D.-det2 :: ( Num t, SubSpace t '[] '[2] '[2] )- => Vector t 2 -> Vector t 2 -> Scalar t-det2 a b = (a ! 1 :* U) * (b ! 2 :* U)- - (a ! 2 :* U) * (b ! 1 :* U)---- | Compose a 3D vector-vec3 :: SubSpace t '[] '[3] '[3] => t -> t -> t -> Vector t 3-vec3 a b c = iwgen f- where- f (1 :* U) = scalar a- f (2 :* U) = scalar b- f _ = scalar c---- | Cross product-cross :: ( Num t, SubSpace t '[] '[3] '[3] )- => Vector t 3 -> Vector t 3 -> Vector t 3-cross a b = vec3 ( unScalar- $ (a ! 2 :* U) * (b ! 3 :* U)- - (a ! 3 :* U) * (b ! 2 :* U) )- ( unScalar- $ (a ! 3 :* U) * (b ! 1 :* U)- - (a ! 1 :* U) * (b ! 3 :* U) )- ( unScalar- $ (a ! 1 :* U) * (b ! 2 :* U)- - (a ! 2 :* U) * (b ! 1 :* U) )----- | Cross product for two vectors in 3D-infixl 7 ×-(×) :: ( Num t, SubSpace t '[] '[3] '[3] )- => Vector t 3 -> Vector t 3 -> Vector t 3-(×) = cross-{-# INLINE (×) #-}----- | Compose a 4D vector-vec4 :: SubSpace t '[] '[4] '[4]- => t -> t -> t -> t -> Vector t 4-vec4 a b c d = iwgen f- where- f (1 :* U) = scalar a- f (2 :* U) = scalar b- f (3 :* U) = scalar c- f _ = scalar d---unpackV2 :: SubSpace t '[] '[2] '[2]- => Vector t 2 -> (t, t)-unpackV2 v = (unScalar $ v ! 1, unScalar $ v ! 2)-{-# INLINE unpackV2 #-}---unpackV3 :: SubSpace t '[] '[3] '[3]- => Vector t 3 -> (t, t, t)-unpackV3 v = (unScalar $ v ! 1, unScalar $ v ! 2, unScalar $ v ! 3)-{-# INLINE unpackV3 #-}---unpackV4 :: SubSpace t '[] '[4] '[4]- => Vector t 4 -> (t, t, t, t)-unpackV4 v = (unScalar $ v ! 1, unScalar $ v ! 2, unScalar $ v ! 3, unScalar $ v ! 4)-{-# INLINE unpackV4 #-}+import Numeric.DataFrame.Internal.Backend ()+import Numeric.Vector.Internal
+ src/Numeric/Vector/Internal.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++module Numeric.Vector.Internal+ ( -- * Type aliases+ Vector+ , Vec2f, Vec3f, Vec4f, Vec2d, Vec3d, Vec4d+ , Vec2i, Vec3i, Vec4i, Vec2w, Vec3w, Vec4w+ -- * Vector constructors+ , Vector2 (..), Vector3 (..), Vector4 (..)+ , DataFrame(Vec2, Vec3, Vec4)+ -- * Common operations+ , (.*.), dot, (·)+ , normL1, normL2, normLPInf, normLNInf, normLP+ , normalized+ , det2, cross, (×)+ ) where++import Numeric.DataFrame.SubSpace+import Numeric.DataFrame.Type+import Numeric.Scalar.Internal++++type Vector (t :: l) (n :: k) = DataFrame t '[n]++type Vec2f = Vector Float 2+type Vec3f = Vector Float 3+type Vec4f = Vector Float 4+type Vec2d = Vector Double 2+type Vec3d = Vector Double 3+type Vec4d = Vector Double 4+type Vec2i = Vector Int 2+type Vec3i = Vector Int 3+type Vec4i = Vector Int 4+type Vec2w = Vector Word 2+type Vec3w = Vector Word 3+type Vec4w = Vector Word 4+++pattern Vec4 :: Vector4 t => t -> t -> t -> t -> Vector t 4+pattern Vec4 a b c d <- (unpackV4# -> (# a, b, c, d #))+ where+ Vec4 = vec4+{-# COMPLETE Vec4 #-}++pattern Vec3 :: Vector3 t => t -> t -> t -> Vector t 3+pattern Vec3 a b c <- (unpackV3# -> (# a, b, c #))+ where+ Vec3 = vec3+{-# COMPLETE Vec3 #-}++pattern Vec2 :: Vector2 t => t -> t -> Vector t 2+pattern Vec2 a b <- (unpackV2# -> (# a, b #))+ where+ Vec2 = vec2+{-# COMPLETE Vec2 #-}++-- | Packing and unpacking 2D vectors+class Vector2 t where+ -- | Compose a 2D vector+ vec2 :: t -> t -> Vector t 2+ -- | Unpack 2D vector elements+ unpackV2# :: Vector t 2 -> (# t, t #)++-- | Packing and unpacking 3D vectors+class Vector3 t where+ -- | Compose a 3D vector+ vec3 :: t -> t -> t -> Vector t 3+ -- | Unpack 3D vector elements+ unpackV3# :: Vector t 3 -> (# t, t, t #)++-- | Packing and unpacking 4D vectors+class Vector4 t where+ -- | Compose a 4D vector+ vec4 :: t -> t -> t -> t -> Vector t 4+ -- | Unpack 4D vector elements+ unpackV4# :: Vector t 4 -> (# t, t, t, t #)++instance {-# OVERLAPPABLE #-} SubSpace t '[2] '[] '[2] => Vector2 t where+ vec2 a b = iwgen f+ where+ f (0 :* U) = scalar a+ f _ = scalar b+ {-# INLINE vec2 #-}+ unpackV2# v =+ (# unScalar (indexOffset# 0# v)+ , unScalar (indexOffset# 1# v) #)+ {-# INLINE unpackV2# #-}++instance {-# OVERLAPPABLE #-} SubSpace t '[3] '[] '[3] => Vector3 t where+ vec3 a b c = iwgen f+ where+ f (0 :* U) = scalar a+ f (1 :* U) = scalar b+ f _ = scalar c+ {-# INLINE vec3 #-}+ unpackV3# v =+ (# unScalar (indexOffset# 0# v)+ , unScalar (indexOffset# 1# v)+ , unScalar (indexOffset# 2# v) #)+ {-# INLINE unpackV3# #-}++instance {-# OVERLAPPABLE #-} SubSpace t '[4] '[] '[4] => Vector4 t where+ vec4 a b c d = iwgen f+ where+ f (0 :* U) = scalar a+ f (1 :* U) = scalar b+ f (2 :* U) = scalar c+ f _ = scalar d+ {-# INLINE vec4 #-}+ unpackV4# v =+ (# unScalar (indexOffset# 0# v)+ , unScalar (indexOffset# 1# v)+ , unScalar (indexOffset# 2# v)+ , unScalar (indexOffset# 3# v) #)+ {-# INLINE unpackV4# #-}++++-- | Scalar product -- sum of Vecs' components products,+-- propagated into whole Vec+(.*.) :: ( Num t+ , Num (Vector t n)+ , SubSpace t '[n] '[] '[n]+ )+ => Vector t n -> Vector t n -> Vector t n+(.*.) a b = fromScalar . ewfoldl (+) 0 $ a * b+infixl 7 .*.++-- | Scalar product -- sum of Vecs' components products -- a scalar+dot :: ( Num t+ , Num (Vector t n)+ , SubSpace t '[n] '[] '[n]+ )+ => Vector t n -> Vector t n -> Scalar t+dot a b = ewfoldl (+) 0 $ a * b++-- | Dot product of two vectors+infixl 7 ·+(·) :: ( Num t+ , Num (Vector t n)+ , SubSpace t '[n] '[] '[n]+ )+ => Vector t n -> Vector t n -> Scalar t+(·) = dot+{-# INLINE (·) #-}+++-- | Sum of absolute values+normL1 :: ( Num t, SubSpace t '[n] '[] '[n] )+ => Vector t n -> Scalar t+normL1 = ewfoldr (\a -> (abs a +)) 0++-- | hypot function (square root of squares)+normL2 :: ( Floating t , SubSpace t '[n] '[] '[n] )+ => Vector t n -> Scalar t+normL2 = sqrt . ewfoldr (\a -> (a*a +)) 0++-- | Normalize vector w.r.t. Euclidean metric (L2).+normalized :: ( Floating t , Fractional (Vector t n), SubSpace t '[n] '[] '[n] )+ => Vector t n -> Vector t n+normalized v = v / n+ where+ n = fromScalar . sqrt $ ewfoldr (\a -> (a*a +)) 0 v++-- | Maximum of absolute values+normLPInf :: ( Ord t, Num t , SubSpace t '[n] '[] '[n] )+ => Vector t n -> Scalar t+normLPInf = ewfoldr (max . abs) 0++-- | Minimum of absolute values+normLNInf :: ( Ord t, Num t , SubSpace t '[n] '[] '[n] )+ => Vector t n -> Scalar t+normLNInf x = ewfoldr (min . abs) (scalar . abs $ ixOff 0 x) x++-- | Norm in Lp space+normLP :: ( Floating t , SubSpace t '[n] '[] '[n] )+ => Int -> Vector t n -> Scalar t+normLP i' = (**ri) . ewfoldr (\a -> (a**i +)) 0+ where+ i = fromIntegral i'+ ri = recip i+{-# INLINE [2] normLP #-}+{-# RULES+"normLP/L1" normLP 1 = normL1+"normLP/L2" normLP 2 = normL2+ #-}++-- | Take a determinant of a matrix composed from two 2D vectors.+-- Like a cross product in 2D.+det2 :: ( Num t, SubSpace t '[2] '[] '[2] )+ => Vector t 2 -> Vector t 2 -> Scalar t+det2 a b = (a ! 0 :* U) * (b ! 1 :* U)+ - (a ! 1 :* U) * (b ! 0 :* U)++-- | Cross product+cross :: ( Num t, SubSpace t '[3] '[] '[3] )+ => Vector t 3 -> Vector t 3 -> Vector t 3+cross a b = vec3 ( unScalar+ $ (a ! 1 :* U) * (b ! 2 :* U)+ - (a ! 2 :* U) * (b ! 1 :* U) )+ ( unScalar+ $ (a ! 2 :* U) * (b ! 0 :* U)+ - (a ! 0 :* U) * (b ! 2 :* U) )+ ( unScalar+ $ (a ! 0 :* U) * (b ! 1 :* U)+ - (a ! 1 :* U) * (b ! 0 :* U) )+++-- | Cross product for two vectors in 3D+infixl 7 ×+(×) :: ( Num t, SubSpace t '[3] '[] '[3] )+ => Vector t 3 -> Vector t 3 -> Vector t 3+(×) = cross+{-# INLINE (×) #-}
test/Numeric/DataFrame/Arbitraries.hs view
@@ -1,61 +1,114 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Provide instance of Arbitrary for all DataFrame types. -- Also, this module is an example of fancy type inference and DataFrame -- traversals with monadic actions. module Numeric.DataFrame.Arbitraries where -import Test.QuickCheck+import Test.QuickCheck +import Data.Kind (Type)+import Data.Semigroup hiding (All) import Numeric.DataFrame import Numeric.Dimensions-import Numeric.PrimBytes+import Numeric.Quaternion+import qualified Numeric.Tuple.Lazy as LT+import qualified Numeric.Tuple.Strict as ST -instance (Arbitrary t, PrimBytes t, Dimensions ds)++maxDims :: Word+maxDims = 5++maxDimSize :: Word+maxDimSize = 7++fromScalarChanceFactor :: Int+fromScalarChanceFactor = 5+++instance (Quaternion t, Arbitrary t, Num t) => Arbitrary (Quater t) where+ arbitrary = sequence+ [ Quater <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+ , Quater <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+ , Quater <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+ , Quater <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+ , Quater <$> arbitrary <*> pure 0 <*> pure 0 <*> pure 0+ , Quater <$> pure 0 <*> arbitrary <*> pure 0 <*> pure 0+ , Quater <$> pure 0 <*> pure 0 <*> arbitrary <*> pure 0+ , Quater <$> pure 0 <*> pure 0 <*> pure 0 <*> arbitrary+ , Quater <$> arbitrary <*> arbitrary <*> pure 0 <*> pure 0+ , Quater <$> arbitrary <*> pure 0 <*> arbitrary <*> pure 0+ , Quater <$> arbitrary <*> pure 0 <*> pure 0 <*> arbitrary+ , Quater <$> pure 0 <*> arbitrary <*> arbitrary <*> pure 0+ , Quater <$> pure 0 <*> arbitrary <*> pure 0 <*> arbitrary+ , Quater <$> pure 0 <*> pure 0 <*> arbitrary <*> arbitrary+ , Quater <$> arbitrary <*> arbitrary <*> arbitrary <*> pure 0+ , Quater <$> arbitrary <*> arbitrary <*> pure 0 <*> arbitrary+ , Quater <$> arbitrary <*> pure 0 <*> arbitrary <*> arbitrary+ , Quater <$> pure 0 <*> arbitrary <*> arbitrary <*> arbitrary+ ] >>= elements++ shrink (Quater x y z t)+ -- shrink either real or the whole imaginary part+ = ($) <$> zipWith3 Quater (shrink x) (shrink y) (shrink z) <*> shrink t++++instance (Arbitrary t, PrimBytes t, Num t, Ord t, Dimensions ds) => Arbitrary (DataFrame t (ds :: [Nat])) where arbitrary | -- First, we need to find out exact array implementation to use -- inside this DataFrame. -- We need to do that whenever exact value of ds is not known- E <- inferASing' @t @ds- -- Then, we need to get basic byte manipulation type classes, such as- -- PrimBytes and PrimArray.- , E <- inferPrim' @t @ds+ Dict <- inferKnownBackend @t @ds -- After that, GHC can infer all necessary fancy things like SubSpace -- to do complex operations on sub-dimensions of a DataFrame. -- -- Note, we could put SubSpace into constraints of this instance as well. -- That would render the above lines unnecessary, but would make -- inference more difficult later.- = arbitrary >>= elementWise @_ @_ @ds f . ewgen . scalar+ = do+ full <- (1 < ) <$> choose (1, fromScalarChanceFactor)+ if full -- I want to check fromScalar code path sometimes+ then arbitrary >>= elementWise @_ @ds @'[] f . ewgen . scalar+ else fromScalar . scalar <$> arbitrary where f :: Arbitrary a => Scalar a -> Gen (Scalar a) f _ = scalar <$> arbitrary- shrink- | E <- inferASing' @t @ds- , E <- inferPrim' @t @ds- = elementWise @_ @_ @ds f- where- -- Unfortunately, Scalar is not a proper second-rank data type- -- (it is just type alias for DataFrame t []).- -- So it cannot be functor or traversable.- f :: Arbitrary a => Scalar a -> [Scalar a]- f = fmap scalar . shrink . unScalar+ shrink df+ | Dict <- inferKnownBackend @t @ds+ , mma <- ewfoldMap @t @ds @'[] @ds+ ((\x -> if x == 0 then Nothing else Just (Max x)) . abs) df+ = case mma of+ Nothing+ -> [] -- all-zero is the most primitive DF possible+ Just (Max ma)+ -> [ ewmap (\x -> if abs x == ma then 0 else x) df+ , ewmap (scalar . withAbs . unScalar) df+ ]+ where+ withAbs :: t -> t+ withAbs x+ | abs x <= 1 = 0+ | otherwise = signum x * closest2 (abs x) 1+ closest2 :: t -> t -> t+ closest2 x b = if x <= b * 2 then b else closest2 x (b*2) -instance (All Arbitrary ts, All PrimBytes ts, RepresentableList ts, Dimensions ds)+instance ( All Arbitrary ts, All PrimBytes ts, All Num ts, All Ord ts+ , RepresentableList ts, Dimensions ds) => Arbitrary (DataFrame ts (ds :: [Nat])) where -- We create arbitrary MultiFrame by combining several SingleFrames. -- SingleFrames are "variables" or "columns" of a MultiFrame that are@@ -71,28 +124,22 @@ at <- arbitrary ats' <- arbitrary @(DataFrame ts' ds) return (at :*: ats')- shrink Z = [] -- MultiFrame is a newtype wrapper on a TypedList. -- Thus, we can always recover RepresentableList ts by using function @types@ shrink (at :*: ats@(MultiFrame ats')) | TypeList <- types ats' = (:*:) <$> shrink at <*> shrink ats+ shrink _ = [] -maxDims :: Word-maxDims = 5--maxDimSize :: Word-maxDimSize = 7- instance KnownDim a => Arbitrary (Dim (N a)) where- arbitrary = return $ Dn (dim @_ @a)+ arbitrary = return $ Dn (dim @a) shrink _ = [] instance KnownDim m => Arbitrary (Dim (XN m)) where arbitrary = do dimN <- choose (dimVal' @m, maxDims)- case constrain @m (someDimVal dimN) of+ case constrainDim @XNat @(XN m) (someDimVal dimN) of Nothing -> error "impossible argument" Just d -> return d shrink _ = []@@ -117,42 +164,111 @@ arbitrary = (:*) <$> arbitrary <*> arbitrary shrink _ = [] -instance (Arbitrary t, PrimBytes t)+instance (Arbitrary t, PrimBytes t, Num t, Ord t) => Arbitrary (SomeDataFrame t) where arbitrary = do -- Generate random dimension list+ SomeDims ds <- arbitrary -- and pattern-match against it with Dims pattern. -- This gives Dimensions ds evidence immediately.- SomeDims (Dims :: Dims ds) <- arbitrary- -- We also need to figure out an array implementation...- case inferASing' @t @ds of- -- ... and generating a random DataFrame becomes a one-liner- E -> SomeDataFrame <$> arbitrary @(DataFrame t ds)- shrink _ = []+ case ds of+ -- We also need to figure out an array implementation...+ (Dims :: Dims ds) -> case inferKnownBackend @t @ds of+ -- ... and generating a random DataFrame becomes a one-liner+ Dict -> SomeDataFrame <$> arbitrary @(DataFrame t ds)+ shrink (SomeDataFrame df) = SomeDataFrame <$> shrink df -- All same as above, just change constraints a bit-instance (All Arbitrary ts, All PrimBytes ts, RepresentableList ts)+instance ( All Arbitrary ts, All PrimBytes ts, All Num ts, All Ord ts+ , RepresentableList ts) => Arbitrary (SomeDataFrame ts) where arbitrary = do- SomeDims (Dims :: Dims ds) <- arbitrary- case inferASing' @ts @ds of- E -> SomeDataFrame <$> arbitrary @(DataFrame ts ds)- shrink _ = []+ SomeDims ds <- arbitrary+ case ds of+ (Dims :: Dims ds) -> case inferKnownBackend @ts @ds of+ Dict -> SomeDataFrame <$> arbitrary @(DataFrame ts ds)+ shrink (SomeDataFrame df) = SomeDataFrame <$> shrink df -instance ( Arbitrary t, PrimBytes t+instance ( Arbitrary t, PrimBytes t, Num t, Ord t , Arbitrary (Dims xs), All KnownXNatType xs) => Arbitrary (DataFrame t (xs :: [XNat])) where arbitrary = do- XDims (_ :: Dims ds) <- arbitrary @(Dims xs)- case inferASing' @t @ds of- E -> XFrame <$> arbitrary @(DataFrame t ds)+ ds <- arbitrary @(Dims xs)+ case ds of+ XDims (_ :: Dims ds) -> case inferKnownBackend @t @ds of+ Dict -> XFrame <$> arbitrary @(DataFrame t ds) shrink (XFrame df) = XFrame <$> shrink df -instance ( All Arbitrary ts, All PrimBytes ts, RepresentableList ts+instance ( All Arbitrary ts, All PrimBytes ts, All Num ts, All Ord ts+ , RepresentableList ts , Arbitrary (Dims xs), All KnownXNatType xs) => Arbitrary (DataFrame ts (xs :: [XNat])) where arbitrary = do- XDims (_ :: Dims ds) <- arbitrary @(Dims xs)- case inferASing' @ts @ds of- E -> XFrame <$> arbitrary @(DataFrame ts ds)+ ds <- arbitrary @(Dims xs)+ case ds of+ XDims (_ :: Dims ds) -> case inferKnownBackend @ts @ds of+ Dict -> XFrame <$> arbitrary @(DataFrame ts ds) shrink (XFrame df) = XFrame <$> shrink df+++instance KnownDim n => Arbitrary (Idx n) where+ arbitrary = elements [0..]++instance Dimensions ns => Arbitrary (Idxs ns) where+ arbitrary = go (Dims @ns)+ where+ go :: forall (bs :: [Nat]) . Dims bs -> Gen (Idxs bs)+ go U = pure U+ go (D :* bs) = (:*) <$> arbitrary <*> go bs++instance (RepresentableList xs, All Arbitrary xs) => Arbitrary (ST.Tuple xs) where+ arbitrary = go (tList @Type @xs)+ where+ go :: forall (bs :: [Type])+ . All Arbitrary bs+ => TypeList bs -> Gen (ST.Tuple bs)+ go U = pure U+ go (_ :* bs) = (ST.:$) <$> arbitrary <*> go bs++instance (RepresentableList xs, All Arbitrary xs) => Arbitrary (LT.Tuple xs) where+ arbitrary = go (tList @Type @xs)+ where+ go :: forall (bs :: [Type])+ . All Arbitrary bs+ => TypeList bs -> Gen (LT.Tuple bs)+ go U = pure U+ go (_ :* bs) = (LT.:$) <$> arbitrary <*> go bs++data AnyMatrix+data NonSingular++data SomeSquareMatrix prop t+ = forall (n :: Nat)+ . (KnownDim n, KnownBackend t '[n], KnownBackend t '[n, n])+ => SSM (DataFrame t '[n,n])++instance (Show t, PrimBytes t) => Show (SomeSquareMatrix prop t) where+ show (SSM df) = show df++instance (Arbitrary t, PrimBytes t, Num t, Ord t)+ => Arbitrary (SomeSquareMatrix AnyMatrix t) where+ arbitrary = do+ dx <- arbitrary @(Dim (XN 2))+ case dx of+ Dx (D :: Dim n) -> case inferKnownBackend @t @'[n] of+ Dict -> SSM <$> arbitrary @(DataFrame t '[n,n])+ shrink (SSM df)= SSM <$> shrink df++instance (Arbitrary t, PrimBytes t, Num t, Ord t)+ => Arbitrary (SomeSquareMatrix NonSingular t) where+ arbitrary = do+ SSM (someMat :: DataFrame t '[n, n]) <- arbitrary @(SomeSquareMatrix AnyMatrix t)+ -- https://en.wikipedia.org/wiki/Diagonally_dominant_matrix+ return . SSM $+ iwmap @t @'[n] @'[n] @'[n,n]+ @t @'[n] @'[n,n]+ ( \i v ->+ let s = ewfoldl (\a -> (a +) . abs) 1 v+ in update i s v+ ) someMat+ shrink _ = []
test/Numeric/DataFrame/BasicTest.hs view
@@ -15,7 +15,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-}-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-}@@ -26,38 +26,112 @@ module Numeric.DataFrame.BasicTest (runTests) where import Numeric.DataFrame-import Numeric.DataFrame.Arbitraries ()-import Numeric.Dimensions+import Numeric.DataFrame.Arbitraries ()+import qualified Numeric.ProductOrd.NonTransitive as NonTransitive+import qualified Numeric.ProductOrd.Partial as Partial import Test.QuickCheck +{-# ANN module "HLint: ignore Use <" #-}+{-# ANN module "HLint: ignore Use >" #-}+{-# ANN module "HLint: ignore Use >=" #-}+{-# ANN module "HLint: ignore Use <=" #-}+{-# ANN module "HLint: ignore Redundant compare" #-} -prop_Comparisons :: SomeDataFrame '[Float, Float] -> Bool-prop_Comparisons (SomeDataFrame (x :*: y :*: Z))- | E <- inferOrd x- , E <- inferFractional x- = and- [ abs x >= abs x / 2- , abs x <= abs x + abs y- , x <= x, x <= x- , x >= x, y >= y- , x == x, y == y- , x < x + 1, x > x - 1- , abs x >= x, abs (-x) >= (-x)- , x > y ===> x >= y- , x < y ===> x <= y- , not (x >= y) ===> not (x > y)- , not (x <= y) ===> not (x < y)- , x == y ===> and [ not (x > y), not (y < x), x >= y, y <= x ]- , x >= y && x <= y ===> x == y+(===>) :: Bool -> Bool -> Bool+a ===> b = not a || b+infix 2 ===>++prop_vanillaOrdTransitivity :: SomeDataFrame '[Double, Double, Double] -> Property+prop_vanillaOrdTransitivity (SomeDataFrame (x :*: y :*: z :*: Z))+ = property $ (x <= y) && (y <= z) ===> x <= z++vanillaOrdComparisons :: Ord t => t -> t -> Property+vanillaOrdComparisons x y+ = conjoin+ [ counterexample "(x < y) == (compare x y == LT)"+ $ (x < y) == (compare x y == LT)+ , counterexample "(x > y) == (compare x y == GT)"+ $ (x > y) == (compare x y == GT)+ , counterexample "(x == y) == (compare x y == EQ)"+ $ (x == y) == (compare x y == EQ)+ , counterexample "min x y == if x <= y then x else y"+ $ min x y == if x <= y then x else y+ , counterexample "max x y == if x >= y then x else y"+ $ max x y == if x >= y then x else y ]- where- a ===> b = not a || b- infix 2 ===> ++comparisons :: (Ord t, Num t) => t -> t -> Property+comparisons x y+ = conjoin+ [ counterexample "abs x <= abs x + abs y" $ abs x <= abs x + abs y+ , counterexample "x <= x" $ x <= x+ , counterexample "y <= y" $ y <= y+ , counterexample "x >= x" $ x >= x+ , counterexample "y >= y" $ y >= y+ , counterexample "x == x" $ x == x+ , counterexample "y == y" $ y == y+ , counterexample "(x > y) == (y < x)"+ $ (x > y) == (y < x)+ , counterexample "(x >= y) == (y <= x)"+ $ (x >= y) == (y <= x)+ , counterexample "(x < y) == (x <= y && x /= y)"+ $ (x < y) == (x <= y && x /= y)+ , counterexample "(x > y) == (x >= y && x /= y)"+ $ (x > y) == (x >= y && x /= y)+ , counterexample "x < x + 1" $ abs x < 10000000 ===> x < x + 1+ , counterexample "x > x - 1" $ abs x < 10000000 ===> x > x - 1+ , counterexample "abs x >= x" $ abs x >= x+ , counterexample "abs (-x) >= (-x)" $ abs (-x) >= (-x)+ , counterexample "x > y ==> x >= y"+ $ x > y ===> x >= y+ , counterexample "x < y ==> x <= y"+ $ x < y ===> x <= y+ , counterexample "not (x >= y) ==> not (x > y)"+ $ not (x >= y) ===> not (x > y)+ , counterexample "not (x <= y) ==> not (x < y)"+ $ not (x <= y) ===> not (x < y)+ , counterexample "x == y ==> not GT or LT, but GE and LE"+ $ x == y ===> and [ not (x > y), not (y < x), x >= y, y <= x ]+ , counterexample "x >= y && x <= y ==> x == y"+ $ x >= y && x <= y ===> x == y+ ]++prop_comparisonsVanillaOrdFloat :: SomeDataFrame '[Float, Float] -> Property+prop_comparisonsVanillaOrdFloat (SomeDataFrame (x :*: y :*: Z)) =+ comparisons x y .&&. vanillaOrdComparisons x y+prop_comparisonsVanillaOrdDouble :: SomeDataFrame '[Double, Double] -> Property+prop_comparisonsVanillaOrdDouble (SomeDataFrame (x :*: y :*: Z)) =+ comparisons x y .&&. vanillaOrdComparisons x y+prop_comparisonsVanillaOrdInt :: SomeDataFrame '[Int, Int] -> Property+prop_comparisonsVanillaOrdInt (SomeDataFrame (x :*: y :*: Z)) =+ comparisons x y .&&. vanillaOrdComparisons x y+++prop_comparisonsPPOrdFloat :: SomeDataFrame '[Float, Float] -> Property+prop_comparisonsPPOrdFloat (SomeDataFrame (x :*: y :*: Z))+ = comparisons (Partial.ProductOrd x) (Partial.ProductOrd y)+prop_comparisonsPPOrdDouble :: SomeDataFrame '[Double, Double] -> Property+prop_comparisonsPPOrdDouble (SomeDataFrame (x :*: y :*: Z))+ = comparisons (Partial.ProductOrd x) (Partial.ProductOrd y)+prop_comparisonsPPOrdInt :: SomeDataFrame '[Int, Int] -> Property+prop_comparisonsPPOrdInt (SomeDataFrame (x :*: y :*: Z))+ = comparisons (Partial.ProductOrd x) (Partial.ProductOrd y)+++prop_comparisonsNTPOrdFloat :: SomeDataFrame '[Float, Float] -> Property+prop_comparisonsNTPOrdFloat (SomeDataFrame (x :*: y :*: Z))+ = comparisons (NonTransitive.ProductOrd x) (NonTransitive.ProductOrd y)+prop_comparisonsNTPOrdDouble :: SomeDataFrame '[Double, Double] -> Property+prop_comparisonsNTPOrdDouble (SomeDataFrame (x :*: y :*: Z))+ = comparisons (NonTransitive.ProductOrd x) (NonTransitive.ProductOrd y)+prop_comparisonsNTPOrdInt :: SomeDataFrame '[Int, Int] -> Property+prop_comparisonsNTPOrdInt (SomeDataFrame (x :*: y :*: Z))+ = comparisons (NonTransitive.ProductOrd x) (NonTransitive.ProductOrd y)++ prop_Numeric :: SomeDataFrame '[Int, Int] -> Bool prop_Numeric (SomeDataFrame (x :*: y :*: Z))- | E <- inferOrd x- , E <- inferNum x = and [ x + x == 2 * x , x + y == y + x@@ -70,9 +144,7 @@ prop_Floating :: SomeDataFrame '[Double, Double] -> Bool prop_Floating (SomeDataFrame (x :*: y :*: Z))- | E <- inferOrd x- , E <- inferFloating x- , lx <- log (0.01 + abs x)+ | lx <- log (0.01 + abs x) , ly <- log (0.01 + abs y) , eps <- 0.001 = all ((eps >=) . abs)@@ -85,5 +157,6 @@ return []-runTests :: IO Bool-runTests = $quickCheckAll+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
test/Numeric/DataFrame/SubSpaceTest.hs view
@@ -8,10 +8,10 @@ module Numeric.DataFrame.SubSpaceTest (runTests) where -import Numeric.DataFrame-import Numeric.DataFrame.Arbitraries ()-import Numeric.Dimensions-import Test.QuickCheck+import Numeric.DataFrame+import Numeric.DataFrame.Arbitraries ()+import Numeric.Dimensions+import Test.QuickCheck type SFull = '[2,5,4,3,7] type SPref = '[2,5,4]@@ -19,31 +19,31 @@ prop_IndexDimMax :: DataFrame Int SPref -> DataFrame Int SSuff -> Bool prop_IndexDimMax x y =- ((maxBound `inSpaceOf` y) !. z) == x+ (z ! (maxBound `inSpaceOf` x)) == y where- z = ewgen x :: DataFrame Int SFull+ z = ewgen y :: DataFrame Int SFull -prop_IndexCustom1 :: DataFrame Word SPref -> Bool-prop_IndexCustom1 x = (1:*3 !. z) == x+prop_IndexCustom1 :: DataFrame Word SSuff -> Bool+prop_IndexCustom1 x = (z ! 1:*3:*2) == x where z = ewgen x :: DataFrame Word SFull --prop_IndexCustom2 :: DataFrame Double SPref -> Bool-prop_IndexCustom2 x = (2:*2 !. z) %* eye == x- where- z = ewgen x :: DataFrame Double SFull+-- TODO:!+-- prop_IndexCustom2 :: DataFrame Double SSuff -> Bool+-- prop_IndexCustom2 x = (z ! 2:*2:*1) %* eye == x+-- where+-- z = ewgen x :: DataFrame Double SFull -prop_Foldlr :: DataFrame Double SPref -> Bool+prop_Foldlr :: DataFrame Double SSuff -> Bool prop_Foldlr x = abs (ewfoldl (+) 10 z - ewfoldr @_ @SPref (+) 0 z - 10) <= fromScalar (zmax * 0.0001) where z = ewgen x :: DataFrame Double SFull- zmax = ewfoldl @Double @'[] @SFull (max . abs) 0.001 z+ zmax = ewfoldl @Double @SFull @'[] (max . abs) 0.001 z prop_Ewmap :: DataFrame Double SFull -> Bool-prop_Ewmap x = x * 2 == ewmap @_ @'[Head SFull] (*2) x+prop_Ewmap x = x * 2 == ewmap @_ @_ @'[Last SFull] (*2) x prop_ProdTranspose :: DataFrame Double '[2,6] -> DataFrame Double '[6,7] -> Bool prop_ProdTranspose x y = transpose (x %* y) == transpose y %* transpose x@@ -52,5 +52,6 @@ prop_Eye x = eye %* x == x && x %* eye == x return []-runTests :: IO Bool-runTests = $quickCheckAll+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
test/Numeric/MatrixDoubleTest.hs view
@@ -10,146 +10,161 @@ module Numeric.MatrixDoubleTest (runTests) where -import Data.Fixed-import Numeric.DataFrame-import Numeric.DataFrame.Arbitraries ()-import Numeric.DataFrame.Internal.Array.Class-import Numeric.Dimensions-import Numeric.PrimBytes-import Test.QuickCheck+import Data.Fixed+import Data.Semigroup+import Numeric.DataFrame+import Numeric.DataFrame.Arbitraries+import Numeric.Dimensions+import Test.QuickCheck -eps :: Scd-eps = 0.0000001+type TestElem = Double+type TestDF = DataFrame TestElem -dropW :: (SubSpace t '[] '[3] '[3], SubSpace t '[] '[4] '[4]) => Vector t 4 -> Vector t 3-dropW v | (x,y,z,_) <- unpackV4 v = vec3 x y z+eps :: Scalar TestElem+eps = 0.000000001 +dropW :: (SubSpace t '[3] '[] '[3], SubSpace t '[4] '[] '[4])+ => Vector t 4 -> Vector t 3+dropW (Vec4 x y z _) = Vec3 x y z++-- | Most of the time, the error is proportional to the maginutude of the biggest element+maxElem :: (SubSpace TestElem ds '[] ds)+ => TestDF (ds :: [Nat]) -> Scalar TestElem+maxElem = ewfoldl (\a -> max a . abs) 0++-- | For operations like @det@, the error is proportional to maximum possible product+-- over rows or columns+maxRows :: forall ds+ . (SubSpace TestElem '[Head ds] (Tail ds) ds)+ => TestDF (ds :: [Nat]) -> Scalar TestElem+maxRows = getProduct . ewfoldMap @_ @'[Head ds] @(Tail ds) @ds (Product . maxElem)+ approxEq ::- forall (ds :: [Nat]).+ forall (ds :: [Nat]) . ( Dimensions ds,- Num (DataFrame Double ds),- PrimBytes (DataFrame Double ds),- PrimArray Double (DataFrame Double ds)+ Num (TestDF ds),+ PrimBytes (TestDF ds),+ PrimArray TestElem (TestDF ds) ) =>- DataFrame Double ds -> DataFrame Double ds -> Bool-approxEq a b = (eps >=) . ewfoldl @_ @'[] max 0 . abs $ a - b+ TestDF ds -> TestDF ds -> Bool+approxEq a b = maxElem (a - b) <= eps * m+ where+ m = maxElem a `max` maxElem b infix 4 `approxEq` -prop_detTranspose :: Matrix '[Double, Double] (XN 2) (XN 2) -> Bool-prop_detTranspose (XFrame (x :*: y :*: Z))- | -- infer KnownDim for both dimensions of matrix x (and y)- KnownDims <- dims `inSpaceOf` x- = let m = diag (ewfoldl max 0 $ abs x) + x %* transpose y- a = det m+prop_detTranspose :: SomeSquareMatrix AnyMatrix TestElem -> Property+prop_detTranspose (SSM m)+ = let a = det m b = det $ transpose m- in abs (a - b) / (abs a + abs b + 1) <= eps+ n = (case dims `inSpaceOf` m of dn :* _ -> dimVal dn) :: Word+ mag = eps * maxRows m * fromIntegral (product [1..n])+ in counterexample+ (unlines+ [ "failed det/transpose:"+ , "m: " ++ show m+ , "mT: " ++ show (transpose m)+ , show a ++ " /= " ++ show b+ ++ " (tolerance: " ++ show mag ++ ")."+ ]+ ) $ abs (a - b) <= mag -prop_inverse :: Matrix '[Double, Double] (XN 2) (XN 2) -> Bool-prop_inverse (XFrame (x :*: y :*: Z))- | -- infer KnownDim for both dimensions of matrix x (and y)- (KnownDims :: Dims ns) <- dims `inSpaceOf` x- -- cumbersose inverse instance requires PrimBytes (Vector t n)- , E <- inferASing' @Double @'[Head ns]- , E <- inferPrim' @Double @'[Head ns]- = let m = diag base + x %* transpose y- mi = inverse m- err a b = ewfoldl max 0 (abs (b - a)) / base- base = ewfoldl max 0.5 (abs x) + ewfoldl max 0.5 (abs y)- in err eye (m %* mi) <= eps- && err eye (mi %* m) <= eps+prop_inverse :: SomeSquareMatrix NonSingular TestElem -> Property+prop_inverse (SSM m)+ = let mi = inverse m+ aeq a b = maxElem (b - a) <= eps * maxRows m+ in counterexample ("failed inverse:" +++ show (m, mi, m %* mi, mi %* m)) $+ aeq eye (m %* mi) && aeq eye (mi %* m) -prop_LU :: Matrix '[Double, Double] (XN 2) (XN 2) -> Bool-prop_LU (XFrame (x :*: y :*: Z))- | -- infer KnownDim for both dimensions of matrix x (and y)- (KnownDims :: Dims ns) <- dims `inSpaceOf` x- -- cumbersose inverse instance requires PrimBytes (Vector t n)- , E <- inferASing' @Double @'[Head ns]- , E <- inferPrim' @Double @'[Head ns]- = let m = diag base + x %* transpose y- f = lu m- err a b = ewfoldl max 0 (abs (b - a)) / base- base = ewfoldl max 0.5 (abs x) + ewfoldl max 0.5 (abs y)- in err (luPerm f %* m) (luLower f %* luUpper f) <= eps+prop_LU :: SomeSquareMatrix NonSingular TestElem -> Bool+prop_LU (SSM m)+ = let f = lu m+ aeq a b = maxElem (b - a) <= eps * maxRows m+ in aeq (luPerm f %* m) (luLower f %* luUpper f) -prop_translate3vs4 :: Vector Double 4 -> Bool+prop_translate3vs4 :: Vector TestElem 4 -> Bool prop_translate3vs4 v = translate4 v == translate3 (dropW v)- -prop_translate4 :: Vector Double 4 -> Vector Double 3 -> Bool-prop_translate4 a b = translate4 a %* toHomPoint b == toHomPoint (dropW a + b) -prop_translate3 :: Vector Double 3 -> Vector Double 3 -> Bool-prop_translate3 a b = translate3 a %* toHomPoint b == toHomPoint (a + b)+prop_translate4 :: Vector TestElem 4 -> Vector TestElem 3 -> Bool+prop_translate4 a b = toHomPoint b %* translate4 a == toHomPoint (dropW a + b) -prop_rotateX :: Vector Double 4 -> Bool-prop_rotateX v | (x,y,z,w) <- unpackV4 v =- and [- rotateX (-2 * pi) %* v `approxEq` v,- rotateX (-1.5 * pi) %* v `approxEq` vec4 x (-z) y w,- rotateX (-pi) %* v `approxEq` vec4 x (-y) (-z) w,- rotateX (-0.5 * pi) %* v `approxEq` vec4 x z (-y) w,- rotateX 0 %* v `approxEq` v,- rotateX (0.5 * pi) %* v `approxEq` vec4 x (-z) y w,- rotateX pi %* v `approxEq` vec4 x (-y) (-z) w,- rotateX (1.5 * pi) %* v `approxEq` vec4 x z (-y) w,- rotateX (2 * pi) %* v `approxEq` v+prop_translate3 :: Vector TestElem 3 -> Vector TestElem 3 -> Bool+prop_translate3 a b = toHomPoint b %* translate3 a == toHomPoint (a + b)++prop_rotateX :: Vector TestElem 4 -> Property+prop_rotateX v@(Vec4 x y z w) =+ conjoin [+ v %* rotateX (-2 * pi) `approxEq` v,+ v %* rotateX (-1.5 * pi) `approxEq` vec4 x (-z) y w,+ v %* rotateX (-pi) `approxEq` vec4 x (-y) (-z) w,+ v %* rotateX (-0.5 * pi) `approxEq` vec4 x z (-y) w,+ v %* rotateX 0 `approxEq` v,+ v %* rotateX (0.5 * pi) `approxEq` vec4 x (-z) y w,+ v %* rotateX pi `approxEq` vec4 x (-y) (-z) w,+ v %* rotateX (1.5 * pi) `approxEq` vec4 x z (-y) w,+ v %* rotateX (2 * pi) `approxEq` v ] -prop_rotateY :: Vector Double 4 -> Bool-prop_rotateY v | (x,y,z,w) <- unpackV4 v =- and [- rotateY (-2 * pi) %* v `approxEq` v,- rotateY (-1.5 * pi) %* v `approxEq` vec4 z y (-x) w,- rotateY (-pi) %* v `approxEq` vec4 (-x) y (-z) w,- rotateY (-0.5 * pi) %* v `approxEq` vec4 (-z) y x w,- rotateY 0 %* v `approxEq` v,- rotateY (0.5 * pi) %* v `approxEq` vec4 z y (-x) w,- rotateY pi %* v `approxEq` vec4 (-x) y (-z) w,- rotateY (1.5 * pi) %* v `approxEq` vec4 (-z) y x w,- rotateY (2 * pi) %* v `approxEq` v+prop_rotateY :: Vector TestElem 4 -> Property+prop_rotateY v@(Vec4 x y z w) =+ conjoin [+ v %* rotateY (-2 * pi) `approxEq` v,+ v %* rotateY (-1.5 * pi) `approxEq` vec4 z y (-x) w,+ v %* rotateY (-pi) `approxEq` vec4 (-x) y (-z) w,+ v %* rotateY (-0.5 * pi) `approxEq` vec4 (-z) y x w,+ v %* rotateY 0 `approxEq` v,+ v %* rotateY (0.5 * pi) `approxEq` vec4 z y (-x) w,+ v %* rotateY pi `approxEq` vec4 (-x) y (-z) w,+ v %* rotateY (1.5 * pi) `approxEq` vec4 (-z) y x w,+ v %* rotateY (2 * pi) `approxEq` v ] -prop_rotateZ :: Vector Double 4 -> Bool-prop_rotateZ v | (x,y,z,w) <- unpackV4 v =- and [- rotateZ (-2 * pi) %* v `approxEq` v,- rotateZ (-1.5 * pi) %* v `approxEq` vec4 (-y) x z w,- rotateZ (-pi) %* v `approxEq` vec4 (-x) (-y) z w,- rotateZ (-0.5 * pi) %* v `approxEq` vec4 y (-x) z w,- rotateZ 0 %* v `approxEq` v,- rotateZ (0.5 * pi) %* v `approxEq` vec4 (-y) x z w,- rotateZ pi %* v `approxEq` vec4 (-x) (-y) z w,- rotateZ (1.5 * pi) %* v `approxEq` vec4 y (-x) z w,- rotateZ (2 * pi) %* v `approxEq` v+prop_rotateZ :: Vector TestElem 4 -> Property+prop_rotateZ v@(Vec4 x y z w) =+ conjoin [+ v %* rotateZ (-2 * pi) `approxEq` v,+ v %* rotateZ (-1.5 * pi) `approxEq` vec4 (-y) x z w,+ v %* rotateZ (-pi) `approxEq` vec4 (-x) (-y) z w,+ v %* rotateZ (-0.5 * pi) `approxEq` vec4 y (-x) z w,+ v %* rotateZ 0 `approxEq` v,+ v %* rotateZ (0.5 * pi) `approxEq` vec4 (-y) x z w,+ v %* rotateZ pi `approxEq` vec4 (-x) (-y) z w,+ v %* rotateZ (1.5 * pi) `approxEq` vec4 y (-x) z w,+ v %* rotateZ (2 * pi) `approxEq` v ] -prop_rotate :: Double -> Bool+prop_rotate :: TestElem -> Property prop_rotate a =- and [+ conjoin [ rotate (vec3 1 0 0) a `approxEq` rotateX a, rotate (vec3 0 1 0) a `approxEq` rotateY a, rotate (vec3 0 0 1) a `approxEq` rotateZ a ] -prop_rotateEuler :: Double -> Double -> Double -> Bool-prop_rotateEuler pitch yaw roll = rotateEuler pitch yaw roll `approxEq` rotateX pitch %* rotateY yaw %* rotateZ roll+prop_rotateEuler :: TestElem -> TestElem -> TestElem -> Bool+prop_rotateEuler pitch yaw roll =+ rotateEuler pitch yaw roll `approxEq` rotateZ roll %* rotateY yaw %* rotateX pitch -prop_lookAt :: Vector Double 3 -> Vector Double 3 -> Vector Double 3 -> Bool+prop_lookAt :: Vector TestElem 3 -> Vector TestElem 3 -> Vector TestElem 3 -> Property prop_lookAt up cam foc =- and [- (normalized . fromHom $ m %* toHomPoint foc) `approxEq` vec3 0 0 (-1),- fromHom (m %* toHomPoint cam) `approxEq` 0,- fromHom (m %* toHomVector xb) `approxEq` vec3 1 0 0,- fromHom (m %* toHomVector yb) `approxEq` vec3 0 1 0,- fromHom (m %* toHomVector zb) `approxEq` vec3 0 0 1+ (apart cam foc && apart up cam) ==>+ conjoin [+ (normalized . fromHom $ toHomPoint foc %* m) `approxEq` vec3 0 0 (-1),+ fromHom (toHomPoint cam %* m) `approxEq` 0,+ fromHom (toHomVector xb %* m) `approxEq` vec3 1 0 0,+ fromHom (toHomVector yb %* m) `approxEq` vec3 0 1 0,+ fromHom (toHomVector zb %* m) `approxEq` vec3 0 0 1 ] where+ apart :: Vector TestElem 3 -> Vector TestElem 3 -> Bool+ apart a b = maxElem (a - b) > 0.01 * (maxElem a `max` maxElem b) m = lookAt up cam foc zb = normalized $ cam - foc xb = normalized $ up `cross` zb yb = zb `cross` xb -prop_perspective :: Double -> Double -> Double -> Double -> Bool+prop_perspective :: TestElem -> TestElem -> TestElem -> TestElem -> Bool prop_perspective a b c d = and [ projectTo 0 0 n `approxEq` vec3 0 0 (-1),@@ -171,9 +186,9 @@ hpd = tan (fovy * 0.5) -- height/distance wpd = aspect * hpd -- width/distance m = perspective n f fovy aspect- projectTo x' y' z = fromHom $ m %* vec4 (x' * wpd * z) (y' * hpd * z) (-z) 1+ projectTo x' y' z = fromHom $ vec4 (x' * wpd * z) (y' * hpd * z) (-z) 1 %* m -prop_orthogonal :: Double -> Double -> Double -> Double -> Bool+prop_orthogonal :: TestElem -> TestElem -> TestElem -> TestElem -> Bool prop_orthogonal a b c d = and [ projectTo 0 0 n `approxEq` vec3 0 0 (-1),@@ -193,20 +208,21 @@ w = 1.0 + mod' c 9999.0 -- Width in range [1, 10000) h = 1.0 + mod' d 9999.0 -- Height in range [1, 10000) m = orthogonal n f w h- projectTo x' y' z = fromHom $ m %* vec4 (x' * w * 0.5) (y' * h * 0.5) (-z) 1+ projectTo x' y' z = fromHom $ vec4 (x' * w * 0.5) (y' * h * 0.5) (-z) 1 %* m -prop_toHomPoint :: Vector Double 3 -> Bool-prop_toHomPoint v | (x,y,z) <- unpackV3 v = toHomPoint v == vec4 x y z 1+prop_toHomPoint :: Vector TestElem 3 -> Bool+prop_toHomPoint v@(Vec3 x y z) = toHomPoint v == vec4 x y z 1 -prop_toHomVector :: Vector Double 3 -> Bool-prop_toHomVector v | (x,y,z) <- unpackV3 v = toHomVector v == vec4 x y z 0+prop_toHomVector :: Vector TestElem 3 -> Bool+prop_toHomVector v@(Vec3 x y z) = toHomVector v == vec4 x y z 0 -prop_fromHom :: Vector Double 4 -> Bool-prop_fromHom v | (x,y,z,w) <- unpackV4 v =+prop_fromHom :: Vector TestElem 4 -> Bool+prop_fromHom v@(Vec4 x y z w) = case w of 0 -> fromHom v == vec3 x y z _ -> fromHom v `approxEq` vec3 (x/w) (y/w) (z/w) return []-runTests :: IO Bool-runTests = $quickCheckAll+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
test/Numeric/MatrixFloatTest.hs view
@@ -10,146 +10,167 @@ module Numeric.MatrixFloatTest (runTests) where -import Data.Fixed-import Numeric.DataFrame-import Numeric.DataFrame.Arbitraries ()-import Numeric.DataFrame.Internal.Array.Class-import Numeric.Dimensions-import Numeric.PrimBytes-import Test.QuickCheck+import Data.Fixed+import Data.Semigroup+import Numeric.DataFrame+import Numeric.DataFrame.Arbitraries+import Numeric.Dimensions+import Test.QuickCheck -eps :: Scf-eps = 0.01+type TestElem = Float+type TestDF = DataFrame TestElem -dropW :: (SubSpace t '[] '[3] '[3], SubSpace t '[] '[4] '[4]) => Vector t 4 -> Vector t 3-dropW v | (x,y,z,_) <- unpackV4 v = vec3 x y z+eps :: Scalar TestElem+eps = 0.00001 +dropW :: (SubSpace t '[3] '[] '[3], SubSpace t '[4] '[] '[4])+ => Vector t 4 -> Vector t 3+dropW (Vec4 x y z _) = Vec3 x y z++-- | Most of the time, the error is proportional to the maginutude of the biggest element+maxElem :: (SubSpace TestElem ds '[] ds)+ => TestDF (ds :: [Nat]) -> Scalar TestElem+maxElem = ewfoldl (\a -> max a . abs) 0++-- | For operations like @det@, the error is proportional to maximum possible product+-- over rows or columns+maxRows :: forall ds+ . (SubSpace TestElem '[Head ds] (Tail ds) ds)+ => TestDF (ds :: [Nat]) -> Scalar TestElem+maxRows = getProduct . ewfoldMap @_ @'[Head ds] @(Tail ds) @ds (Product . maxElem)+ approxEq ::- forall (ds :: [Nat]).+ forall (ds :: [Nat]) . ( Dimensions ds,- Num (DataFrame Float ds),- PrimBytes (DataFrame Float ds),- PrimArray Float (DataFrame Float ds)+ Num (TestDF ds),+ PrimBytes (TestDF ds),+ PrimArray TestElem (TestDF ds) ) =>- DataFrame Float ds -> DataFrame Float ds -> Bool-approxEq a b = (eps >=) . ewfoldl @_ @'[] max 0 . abs $ a - b+ TestDF ds -> TestDF ds -> Bool+approxEq a b = maxElem (a - b) <= eps * m+ where+ m = maxElem a `max` maxElem b infix 4 `approxEq` -prop_detTranspose :: Matrix '[Float, Float] (XN 2) (XN 2) -> Bool-prop_detTranspose (XFrame (x :*: y :*: Z))- | -- infer KnownDim for both dimensions of matrix x (and y)- KnownDims <- dims `inSpaceOf` x- = let m = diag (ewfoldl max 0 $ abs x) + x %* transpose y- a = det m+prop_detTranspose :: SomeSquareMatrix AnyMatrix TestElem -> Property+prop_detTranspose (SSM m)+ = let a = det m b = det $ transpose m- in abs (a - b) / (abs a + abs b + 1) <= eps+ n = (case dims `inSpaceOf` m of dn :* _ -> dimVal dn) :: Word+ mag = eps * maxRows m * fromIntegral (product [1..n])+ in counterexample+ (unlines+ [ "failed det/transpose:"+ , "m: " ++ show m+ , "mT: " ++ show (transpose m)+ , show a ++ " /= " ++ show b+ ++ " (tolerance: " ++ show mag ++ ")."+ ]+ ) $ abs (a - b) <= mag -prop_inverse :: Matrix '[Float, Float] (XN 2) (XN 2) -> Bool-prop_inverse (XFrame (x :*: y :*: Z))- | -- infer KnownDim for both dimensions of matrix x (and y)- (KnownDims :: Dims ns) <- dims `inSpaceOf` x- -- cumbersose inverse instance requires PrimBytes (Vector t n)- , E <- inferASing' @Float @'[Head ns]- , E <- inferPrim' @Float @'[Head ns]- = let m = diag base + x %* transpose y- mi = inverse m- err a b = ewfoldl max 0 (abs (b - a)) / base- base = ewfoldl max 0.5 (abs x) + ewfoldl max 0.5 (abs y)- in err eye (m %* mi) <= eps- && err eye (mi %* m) <= eps+prop_inverse :: SomeSquareMatrix NonSingular TestElem -> Property+prop_inverse (SSM m)+ = let mi = inverse m+ aeq a b = maxElem (b - a) <= eps * maxRows m+ in counterexample ("failed inverse:" +++ show (m, mi, m %* mi, mi %* m)) $+ aeq eye (m %* mi) && aeq eye (mi %* m) -prop_LU :: Matrix '[Float, Float] (XN 2) (XN 2) -> Bool-prop_LU (XFrame (x :*: y :*: Z))- | -- infer KnownDim for both dimensions of matrix x (and y)- (KnownDims :: Dims ns) <- dims `inSpaceOf` x- -- cumbersose inverse instance requires PrimBytes (Vector t n)- , E <- inferASing' @Float @'[Head ns]- , E <- inferPrim' @Float @'[Head ns]- = let m = diag base + x %* transpose y- f = lu m- err a b = ewfoldl max 0 (abs (b - a)) / base- base = ewfoldl max 0.5 (abs x) + ewfoldl max 0.5 (abs y)- in err (luPerm f %* m) (luLower f %* luUpper f) <= eps+-- TODO: improve lu!+-- lu factorization is very unstable in some cases+--+-- >>> m = unsafeFromFlatList (Dims @'[4,4]) 0 [1,0,1,-2, 0,-1,1,2, 2,-4,2,-2, 4,-8,-2,2 ] :: Mat44f+-- >>> det m == 0+-- >>> det (transpose m) == 60+prop_LU :: SomeSquareMatrix NonSingular TestElem -> Bool+prop_LU (SSM m)+ = let f = lu m+ aeq a b = maxElem (b - a) <= eps * maxRows m+ in aeq (luPerm f %* m) (luLower f %* luUpper f) -prop_translate3vs4 :: Vector Float 4 -> Bool+prop_translate3vs4 :: Vector TestElem 4 -> Bool prop_translate3vs4 v = translate4 v == translate3 (dropW v)- -prop_translate4 :: Vector Float 4 -> Vector Float 3 -> Bool-prop_translate4 a b = translate4 a %* toHomPoint b == toHomPoint (dropW a + b) -prop_translate3 :: Vector Float 3 -> Vector Float 3 -> Bool-prop_translate3 a b = translate3 a %* toHomPoint b == toHomPoint (a + b)+prop_translate4 :: Vector TestElem 4 -> Vector TestElem 3 -> Bool+prop_translate4 a b = toHomPoint b %* translate4 a == toHomPoint (dropW a + b) -prop_rotateX :: Vector Float 4 -> Bool-prop_rotateX v | (x,y,z,w) <- unpackV4 v =- and [- rotateX (-2 * pi) %* v `approxEq` v,- rotateX (-1.5 * pi) %* v `approxEq` vec4 x (-z) y w,- rotateX (-pi) %* v `approxEq` vec4 x (-y) (-z) w,- rotateX (-0.5 * pi) %* v `approxEq` vec4 x z (-y) w,- rotateX 0 %* v `approxEq` v,- rotateX (0.5 * pi) %* v `approxEq` vec4 x (-z) y w,- rotateX pi %* v `approxEq` vec4 x (-y) (-z) w,- rotateX (1.5 * pi) %* v `approxEq` vec4 x z (-y) w,- rotateX (2 * pi) %* v `approxEq` v+prop_translate3 :: Vector TestElem 3 -> Vector TestElem 3 -> Bool+prop_translate3 a b = toHomPoint b %* translate3 a == toHomPoint (a + b)++prop_rotateX :: Vector TestElem 4 -> Property+prop_rotateX v@(Vec4 x y z w) =+ conjoin [+ v %* rotateX (-2 * pi) `approxEq` v,+ v %* rotateX (-1.5 * pi) `approxEq` vec4 x (-z) y w,+ v %* rotateX (-pi) `approxEq` vec4 x (-y) (-z) w,+ v %* rotateX (-0.5 * pi) `approxEq` vec4 x z (-y) w,+ v %* rotateX 0 `approxEq` v,+ v %* rotateX (0.5 * pi) `approxEq` vec4 x (-z) y w,+ v %* rotateX pi `approxEq` vec4 x (-y) (-z) w,+ v %* rotateX (1.5 * pi) `approxEq` vec4 x z (-y) w,+ v %* rotateX (2 * pi) `approxEq` v ] -prop_rotateY :: Vector Float 4 -> Bool-prop_rotateY v | (x,y,z,w) <- unpackV4 v =- and [- rotateY (-2 * pi) %* v `approxEq` v,- rotateY (-1.5 * pi) %* v `approxEq` vec4 z y (-x) w,- rotateY (-pi) %* v `approxEq` vec4 (-x) y (-z) w,- rotateY (-0.5 * pi) %* v `approxEq` vec4 (-z) y x w,- rotateY 0 %* v `approxEq` v,- rotateY (0.5 * pi) %* v `approxEq` vec4 z y (-x) w,- rotateY pi %* v `approxEq` vec4 (-x) y (-z) w,- rotateY (1.5 * pi) %* v `approxEq` vec4 (-z) y x w,- rotateY (2 * pi) %* v `approxEq` v+prop_rotateY :: Vector TestElem 4 -> Property+prop_rotateY v@(Vec4 x y z w) =+ conjoin [+ v %* rotateY (-2 * pi) `approxEq` v,+ v %* rotateY (-1.5 * pi) `approxEq` vec4 z y (-x) w,+ v %* rotateY (-pi) `approxEq` vec4 (-x) y (-z) w,+ v %* rotateY (-0.5 * pi) `approxEq` vec4 (-z) y x w,+ v %* rotateY 0 `approxEq` v,+ v %* rotateY (0.5 * pi) `approxEq` vec4 z y (-x) w,+ v %* rotateY pi `approxEq` vec4 (-x) y (-z) w,+ v %* rotateY (1.5 * pi) `approxEq` vec4 (-z) y x w,+ v %* rotateY (2 * pi) `approxEq` v ] -prop_rotateZ :: Vector Float 4 -> Bool-prop_rotateZ v | (x,y,z,w) <- unpackV4 v =- and [- rotateZ (-2 * pi) %* v `approxEq` v,- rotateZ (-1.5 * pi) %* v `approxEq` vec4 (-y) x z w,- rotateZ (-pi) %* v `approxEq` vec4 (-x) (-y) z w,- rotateZ (-0.5 * pi) %* v `approxEq` vec4 y (-x) z w,- rotateZ 0 %* v `approxEq` v,- rotateZ (0.5 * pi) %* v `approxEq` vec4 (-y) x z w,- rotateZ pi %* v `approxEq` vec4 (-x) (-y) z w,- rotateZ (1.5 * pi) %* v `approxEq` vec4 y (-x) z w,- rotateZ (2 * pi) %* v `approxEq` v+prop_rotateZ :: Vector TestElem 4 -> Property+prop_rotateZ v@(Vec4 x y z w) =+ conjoin [+ v %* rotateZ (-2 * pi) `approxEq` v,+ v %* rotateZ (-1.5 * pi) `approxEq` vec4 (-y) x z w,+ v %* rotateZ (-pi) `approxEq` vec4 (-x) (-y) z w,+ v %* rotateZ (-0.5 * pi) `approxEq` vec4 y (-x) z w,+ v %* rotateZ 0 `approxEq` v,+ v %* rotateZ (0.5 * pi) `approxEq` vec4 (-y) x z w,+ v %* rotateZ pi `approxEq` vec4 (-x) (-y) z w,+ v %* rotateZ (1.5 * pi) `approxEq` vec4 y (-x) z w,+ v %* rotateZ (2 * pi) `approxEq` v ] -prop_rotate :: Float -> Bool+prop_rotate :: TestElem -> Property prop_rotate a =- and [+ conjoin [ rotate (vec3 1 0 0) a `approxEq` rotateX a, rotate (vec3 0 1 0) a `approxEq` rotateY a, rotate (vec3 0 0 1) a `approxEq` rotateZ a ] -prop_rotateEuler :: Float -> Float -> Float -> Bool-prop_rotateEuler pitch yaw roll = rotateEuler pitch yaw roll `approxEq` rotateX pitch %* rotateY yaw %* rotateZ roll+prop_rotateEuler :: TestElem -> TestElem -> TestElem -> Bool+prop_rotateEuler pitch yaw roll =+ rotateEuler pitch yaw roll `approxEq` rotateZ roll %* rotateY yaw %* rotateX pitch -prop_lookAt :: Vector Float 3 -> Vector Float 3 -> Vector Float 3 -> Bool+prop_lookAt :: Vector TestElem 3 -> Vector TestElem 3 -> Vector TestElem 3 -> Property prop_lookAt up cam foc =- and [- (normalized . fromHom $ m %* toHomPoint foc) `approxEq` vec3 0 0 (-1),- fromHom (m %* toHomPoint cam) `approxEq` 0,- fromHom (m %* toHomVector xb) `approxEq` vec3 1 0 0,- fromHom (m %* toHomVector yb) `approxEq` vec3 0 1 0,- fromHom (m %* toHomVector zb) `approxEq` vec3 0 0 1+ (apart cam foc && apart up cam) ==>+ conjoin [+ (normalized . fromHom $ toHomPoint foc %* m) `approxEq` vec3 0 0 (-1),+ fromHom (toHomPoint cam %* m) `approxEq` 0,+ fromHom (toHomVector xb %* m) `approxEq` vec3 1 0 0,+ fromHom (toHomVector yb %* m) `approxEq` vec3 0 1 0,+ fromHom (toHomVector zb %* m) `approxEq` vec3 0 0 1 ] where+ apart :: Vector TestElem 3 -> Vector TestElem 3 -> Bool+ apart a b = maxElem (a - b) > 0.01 * (maxElem a `max` maxElem b) m = lookAt up cam foc zb = normalized $ cam - foc xb = normalized $ up `cross` zb yb = zb `cross` xb -prop_perspective :: Float -> Float -> Float -> Float -> Bool+prop_perspective :: TestElem -> TestElem -> TestElem -> TestElem -> Bool prop_perspective a b c d = and [ projectTo 0 0 n `approxEq` vec3 0 0 (-1),@@ -171,9 +192,9 @@ hpd = tan (fovy * 0.5) -- height/distance wpd = aspect * hpd -- width/distance m = perspective n f fovy aspect- projectTo x' y' z = fromHom $ m %* vec4 (x' * wpd * z) (y' * hpd * z) (-z) 1+ projectTo x' y' z = fromHom $ vec4 (x' * wpd * z) (y' * hpd * z) (-z) 1 %* m -prop_orthogonal :: Float -> Float -> Float -> Float -> Bool+prop_orthogonal :: TestElem -> TestElem -> TestElem -> TestElem -> Bool prop_orthogonal a b c d = and [ projectTo 0 0 n `approxEq` vec3 0 0 (-1),@@ -193,20 +214,21 @@ w = 1.0 + mod' c 9999.0 -- Width in range [1, 10000) h = 1.0 + mod' d 9999.0 -- Height in range [1, 10000) m = orthogonal n f w h- projectTo x' y' z = fromHom $ m %* vec4 (x' * w * 0.5) (y' * h * 0.5) (-z) 1+ projectTo x' y' z = fromHom $ vec4 (x' * w * 0.5) (y' * h * 0.5) (-z) 1 %* m -prop_toHomPoint :: Vector Float 3 -> Bool-prop_toHomPoint v | (x,y,z) <- unpackV3 v = toHomPoint v == vec4 x y z 1+prop_toHomPoint :: Vector TestElem 3 -> Bool+prop_toHomPoint v@(Vec3 x y z) = toHomPoint v == vec4 x y z 1 -prop_toHomVector :: Vector Float 3 -> Bool-prop_toHomVector v | (x,y,z) <- unpackV3 v = toHomVector v == vec4 x y z 0+prop_toHomVector :: Vector TestElem 3 -> Bool+prop_toHomVector v@(Vec3 x y z) = toHomVector v == vec4 x y z 0 -prop_fromHom :: Vector Float 4 -> Bool-prop_fromHom v | (x,y,z,w) <- unpackV4 v =+prop_fromHom :: Vector TestElem 4 -> Bool+prop_fromHom v@(Vec4 x y z w) = case w of 0 -> fromHom v == vec3 x y z _ -> fromHom v `approxEq` vec3 (x/w) (y/w) (z/w) return []-runTests :: IO Bool-runTests = $quickCheckAll+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
+ test/Numeric/PrimBytesTest.hs view
@@ -0,0 +1,411 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE EmptyDataDeriving #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+module Numeric.PrimBytesTest (runTests) where++import Data.Int+import Data.Type.Lits+import Data.Word+import Foreign.Marshal+import Foreign.Ptr+import Foreign.Storable+import GHC.Exts+import GHC.Generics+import GHC.Word+import Numeric.DataFrame.Arbitraries ()+import Numeric.Dimensions+import Numeric.PrimBytes+import qualified Numeric.Tuple.Lazy as LT+import qualified Numeric.Tuple.Strict as ST+import Spec.Util+import Test.QuickCheck++data Dummy+ deriving (Generic, Show, Read, Eq, Ord)++data Vertex a b c+ = Vertex+ { pos :: (a, a, a, a)+ , norm :: (b, b, b)+ , tex :: Either (b, b) (c, c, c)+ , extraFloats :: (Float, Double)+ } deriving (Generic, Show, Read, Eq, Ord)++data ManyAlternatives a b c+ = EmptyAlt+ | FirstAlt a b b c+ | SecondAlt a c+ | AltN (Either a b)+ | AltM (Maybe a) (Maybe b) (Maybe c)+ | SecondEmptyAlt+ | SomeWeirdChoice Word8 Word64 Int8 Char Word32 Int16 a+ deriving (Generic, Show, Read, Eq, Ord)++data MyUnboxedType a+ = VeryUnboxed Word# Char# Int# Addr# Float# Double#+ | NotSoUnboxed a a+ | JustABitUnboxed Double# a Char# a+ deriving (Generic, Eq, Ord)++instance Show a => Show (MyUnboxedType a) where+ show (VeryUnboxed w c i a f d)+ = unwords [ "VeryUnboxed", show (W# w), show (I# i)+ , show (C# c), show (Ptr a), show (F# f), show (D# d)]+ show (NotSoUnboxed a b)+ = unwords [ "NotSoUnboxed", show a, show b]+ show (JustABitUnboxed d x c y)+ = unwords [ "JustABitUnboxed ", show (D# d), show x, show (C# c), show y]+++instance (PrimBytes a, PrimBytes b, PrimBytes c)+ => PrimBytes (Vertex a b c)+instance (PrimBytes a, PrimBytes b, PrimBytes c)+ => PrimBytes (ManyAlternatives a b c)+instance (PrimBytes a)+ => PrimBytes (MyUnboxedType a)+instance (PrimBytes a, PrimBytes b, PrimBytes c) => Storable (Vertex a b c) where+ sizeOf = bSizeOf+ alignment = bAlignOf+ peekElemOff = bPeekElemOff+ pokeElemOff = bPokeElemOff+ peekByteOff = bPeekByteOff+ pokeByteOff = bPokeByteOff+ peek = bPeek+ poke = bPoke+instance (PrimBytes a, PrimBytes b, PrimBytes c) => Storable (ManyAlternatives a b c) where+ sizeOf = bSizeOf+ alignment = bAlignOf+ peekElemOff = bPeekElemOff+ pokeElemOff = bPokeElemOff+ peekByteOff = bPeekByteOff+ pokeByteOff = bPokeByteOff+ peek = bPeek+ poke = bPoke+instance PrimBytes a => Storable (MyUnboxedType a) where+ sizeOf = bSizeOf+ alignment = bAlignOf+ peekElemOff = bPeekElemOff+ pokeElemOff = bPokeElemOff+ peekByteOff = bPeekByteOff+ pokeByteOff = bPokeByteOff+ peek = bPeek+ poke = bPoke++instance Arbitrary (Ptr Dummy) where+ arbitrary = intPtrToPtr . IntPtr <$> arbitrary++instance (Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (Vertex a b c) where+ arbitrary = Vertex <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary++instance (Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (ManyAlternatives a b c) where+ arbitrary = choose (1, 7 :: Int) >>= \case+ 1 -> pure EmptyAlt+ 2 -> FirstAlt <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+ 3 -> SecondAlt <$> arbitrary <*> arbitrary+ 4 -> AltN <$> arbitrary+ 5 -> AltM <$> arbitrary <*> arbitrary <*> arbitrary+ 6 -> pure SecondEmptyAlt+ _ -> SomeWeirdChoice <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+ <*> arbitrary <*> arbitrary <*> arbitrary++instance Arbitrary a => Arbitrary (MyUnboxedType a) where+ arbitrary = choose (1, 3 :: Int) >>= \case+ 1 -> do+ W# w <- arbitrary+ C# c <- arbitrary+ I# i <- arbitrary+ Ptr a <- arbitrary :: Gen (Ptr Dummy)+ F# f <- arbitrary+ D# d <- arbitrary+ return $ VeryUnboxed w c i a f d+ 2 -> NotSoUnboxed <$> arbitrary <*> arbitrary+ _ -> do+ C# c <- arbitrary+ D# d <- arbitrary+ x <- arbitrary+ y <- arbitrary+ return $ JustABitUnboxed d x c y++showByteArray :: Int# -> ByteArray# -> [Word8]+showByteArray size ba = go 0#+ where+ go i+ | isTrue# (i <# size) = W8# (indexWord8Array# ba i) : go (i +# 1#)+ | otherwise = []++showMutableByteArray :: Int# -> MutableByteArray# s+ -> State# s -> (# State# s, [Word8] #)+showMutableByteArray size mba = go 0#+ where+ go i s0+ | isTrue# (i <# size)+ , (# s1, w #) <- readWord8Array# mba i s0+ , (# s2, ws #) <- go (i +# 1#) s1+ = (# s2, W8# w : ws #)+ | otherwise = (# s0, [] #)++-- | The most basic property+fromToBytesId :: (PrimBytes a, Eq a, Show a) => a -> Property+fromToBytesId v = counterexample msg $+ v === fromBytes (byteOffset v) bytes+ where+ bytes = getBytes v+ byteList = showByteArray (byteOffset v +# byteSize v) bytes+ msg = unlines+ [ "byteOffset: " ++ show (I# (byteOffset v))+ , "byteAlign: " ++ show (I# (byteAlign v))+ , "byteSize: " ++ show (I# (byteSize v))+ , "Array content: " ++ show byteList+ ]++-- | Pointers+fromToPtrId :: (PrimBytes a, Eq a, Show a) => a -> Property+fromToPtrId v = ioProperty . allocaBytes (bSizeOf v) $ \ptr -> do+ bPoke ptr v+ v1 <- bPeek ptr+ return (v === v1)++-- | Byte offsets+readWriteBytesId :: (PrimBytes a, Eq a, Show a) => Int -> a -> Property+readWriteBytesId off' v = case runRW# go of (# _, r #) -> r+ where+ -- reasonably small offset aligned to a multiple of @byteAlign v@+ off = case abs off' `mod` 100 of I# i -> i *# byteAlign v+ -- write and read the value from an array by a specified offset+ go :: forall s . State# s -> (# State# s, Property #)+ go s0+ | (# s1, mba #) <- newByteArray# (byteSize v +# off) s0+ , s2 <- writeBytes mba off v s1+ , (# s3, w #) <- readBytes mba off s2+ , (# s4, byteList #) <- showMutableByteArray (byteSize v +# off) mba s3+ , (# s5, ba #) <- unsafeFreezeByteArray# mba s4+ , u <- fromBytes off ba+ , msg <- unlines+ [ "Offset 'off': " ++ show (I# off)+ , "byteOffset: " ++ show (I# (byteOffset v))+ , "byteAlign: " ++ show (I# (byteAlign v))+ , "byteSize: " ++ show (I# (byteSize v))+ , "Array content: " ++ show byteList+ ]+ = (# s5, counterexample msg (v === w .&&. v == u) #)++-- | Elem offsets+readWriteArrayId :: (PrimBytes a, Eq a, Show a) => Int -> Int -> a -> Property+readWriteArrayId n' i' v = case runRW# go of (# _, r #) -> r+ where+ -- allocate reasonably small number of elements+ n = case abs n' `mod` 30 of I# x -> x +# 1#+ i = case abs i' `mod` I# n of I# x -> x+ -- write and read the value from an array by a specified offset+ go :: forall s . State# s -> (# State# s, Property #)+ go s0+ | (# s1, mba #) <- newByteArray# (n *# byteSize v) s0+ , s2 <- writeArray mba i v s1+ , (# s3, w #) <- readArray mba i s2+ , (# s4, byteList #) <- showMutableByteArray (n *# byteSize v) mba s3+ , (# s5, ba #) <- unsafeFreezeByteArray# mba s4+ , u <- indexArray ba i+ , msg <- unlines+ [ "Array size: " ++ show (I# n)+ , "Array index: " ++ show (I# i)+ , "byteOffset: " ++ show (I# (byteOffset v))+ , "byteAlign: " ++ show (I# (byteAlign v))+ , "byteSize: " ++ show (I# (byteSize v))+ , "Array content: " ++ show byteList+ ]+ = (# s5, counterexample msg (v === w .&&. v == u) #)+++-- | Working this elem offsets and byte offsets together+mixedTransformsId :: (PrimBytes a, Eq a, Show a) => Int -> Int -> a -> Property+mixedTransformsId n' i' v = case runRW# go of (# _, r #) -> r+ where+ -- allocate reasonably small number of elements+ n = case abs n' `mod` 30 of I# x -> x +# 2#+ i = case abs i' `mod` (I# n - 1) of I# x -> x -- i+1 is always a valid index+ i1 = i +# 1#+ -- write and read the value from an array by a specified offset+ go :: forall s . State# s -> (# State# s, Property #)+ go s0+ | (# s1, mba #) <- newByteArray# (n *# byteSize v) s0+ , s2 <- writeArray mba i1 v s1+ , s3 <- writeBytes mba (i *# byteSize v) v s2+ , (# s4, w #) <- readArray mba i s3+ , (# s5, u #) <- readBytes mba (i1 *# byteSize v) s4+ , (# s6, byteList #) <- showMutableByteArray (n *# byteSize v) mba s5+ , msg <- unlines+ [ "Array size: " ++ show (I# n)+ , "Array index: " ++ show (I# i)+ , "byteOffset: " ++ show (I# (byteOffset v))+ , "byteAlign: " ++ show (I# (byteAlign v))+ , "byteSize: " ++ show (I# (byteSize v))+ , "Array content: " ++ show byteList+ ]+ = (# s6, counterexample msg (v === w .&&. v == u) #)+++class SamePrimRep a b where+ convert :: a -> b++-- | Some times should have the same PrimBytes representation+samePrimRepId :: forall a b+ . ( PrimBytes a, PrimBytes b, Eq b, Show b, SamePrimRep a b)+ => Int -> a -> b -> Property+samePrimRepId off' a b = case runRW# go of (# _, r #) -> r+ where+ f = convert @a @b -- monomorphise it to avoid type errors+ -- reasonably small offset aligned to a multiple of @byteAlign a@+ off = case abs off' `mod` 100 of I# i -> i *# byteAlign a+ -- write and read the value from an array by a specified offset+ go :: forall s . State# s -> (# State# s, Property #)+ go s0+ | (# s1, mba #) <- newByteArray# (off +# byteSize a +# byteSize b) s0+ , s2 <- writeBytes mba off a s1+ , s3 <- writeBytes mba (off +# byteSize a) b s2+ , (# s4, a' #) <- readBytes mba off s3+ , (# s5, b' #) <- readBytes mba (off +# byteSize b) s4+ , (# s6, bl #) <- showMutableByteArray (off +# byteSize a +# byteSize b) mba s5+ , msg <- unlines+ [ "Offset 'off': " ++ show (I# off)+ , "byteOffset: " ++ show (I# (byteOffset a), I# (byteOffset b))+ , "byteAlign: " ++ show (I# (byteAlign a), I# (byteAlign b))+ , "byteSize: " ++ show (I# (byteSize a), I# (byteSize b))+ , "Array content: " ++ show bl+ ]+ = (# s6, counterexample msg (f a === a' .&&. b === f b') #)++-- Check whether @byteFieldOffset@ calculates correct field offsets+vertexFields :: ( PrimBytes a, Eq a, Show a+ , PrimBytes b, Eq b, Show b+ , PrimBytes c, Eq c, Show c)+ => Vertex a b c -> Property+vertexFields v+ | ba <- getBytes v+ , off <- byteOffset v+ = conjoin+ [ counterexample "pos" $ pos v === fromBytes+ (off +# byteFieldOffset (proxy# @Symbol @"pos") v) ba+ , counterexample "norm" $ norm v === fromBytes+ (off +# byteFieldOffset (proxy# @Symbol @"norm") v) ba+ , counterexample "tex" $ tex v === fromBytes+ (off +# byteFieldOffset (proxy# @Symbol @"tex") v) ba+ , counterexample "extraFloats" $ extraFloats v === fromBytes+ (off +# byteFieldOffset (proxy# @Symbol @"extraFloats") v) ba+ ]++++-- a list of types to test the properties against+type SingleVarTypes =+ '[ Word8, Word16, Word32, Word64, Word+ , Int8, Int16, Int32, Int64, Int+ , Char, Double, Float+ , Vertex Double Float Char+ , Vertex Word8 Double Int16+ , Vertex Word16 Word32 Word64+ , Vertex Int64 Int8 Int32+ , ManyAlternatives Word8 Double Double+ , ManyAlternatives Float Double Int16+ , Maybe Int+ , Either Int32 Double+ , MyUnboxedType (Either (Either () Char) Float)+ , MyUnboxedType ()+ , Ptr Dummy+ , Idx 7+ , Idxs ('[] :: [Nat])+ , Idxs '[5, 3, 12]+ , ST.Tuple '[Double, Word8, Word8, Word8, Maybe Float]+ , LT.Tuple '[]+ , LT.Tuple '[Int, Int8, Either Float Double]+ ]++-- I can substitute these in place of parameters of Vertex or ManyAlternatives+type TypeTriples =+ '[ '(Double, Float, Char)+ , '(Word8, Double, Int16)+ , '(Word16, Word32, Word64)+ , '(Word16, Word32, Word64)+ , '(Int64, Int8, Int32)+ , '(Float, Char, Char)+ ]++instance SamePrimRep a (ST.Tuple '[a]) where+ convert a = a ST.:$ U+instance SamePrimRep (a,b) (ST.Tuple '[a,b]) where+ convert (a, b) = a ST.:$ b ST.:$ U+instance SamePrimRep (a,b,c) (ST.Tuple '[a,b,c]) where+ convert (a, b, c) = a ST.:$ b ST.:$ c ST.:$ U+instance SamePrimRep (a,b,c,d) (ST.Tuple '[a,b,c,d]) where+ convert (a, b, c, d) = a ST.:$ b ST.:$ c ST.:$ d ST.:$ U+instance SamePrimRep (a,b,c,d,e) (ST.Tuple '[a,b,c,d,e]) where+ convert (a, b, c, d, e) = a ST.:$ b ST.:$ c ST.:$ d ST.:$ e ST.:$ U++instance SamePrimRep a (LT.Tuple '[a]) where+ convert a = a LT.:$ U+instance SamePrimRep (a,b) (LT.Tuple '[a,b]) where+ convert (a, b) = a LT.:$ b LT.:$ U+instance SamePrimRep (a,b,c) (LT.Tuple '[a,b,c]) where+ convert (a, b, c) = a LT.:$ b LT.:$ c LT.:$ U+instance SamePrimRep (a,b,c,d) (LT.Tuple '[a,b,c,d]) where+ convert (a, b, c, d) = a LT.:$ b LT.:$ c LT.:$ d LT.:$ U+instance SamePrimRep (a,b,c,d,e) (LT.Tuple '[a,b,c,d,e]) where+ convert (a, b, c, d, e) = a LT.:$ b LT.:$ c LT.:$ d LT.:$ e LT.:$ U++instance SamePrimRep (Maybe a) (Either () a) where+ convert (Just a) = Right a+ convert Nothing = Left ()++type SamePrimRepTypes =+ '[ '( (Word, Double), ST.Tuple '[Word, Double] )+ , '( (Double, Word8, Word8, Word8, Maybe Float)+ , ST.Tuple '[Double, Word8, Word8, Word8, Maybe Float] )+ , '( (Word8, Int16, Word32, Either (Either Double Float) Int)+ , LT.Tuple '[Word8, Int16, Word32, Either (Either Double Float) Int] )+ , '( Maybe Float, Either () Float)+ , '( Maybe Double, Either () Double)+ ]++return [] -- this is for $testWithTypes++prop_fromToBytesId :: Property+prop_fromToBytesId = $(testWithTypes 'fromToBytesId ''SingleVarTypes)++prop_fromToPtrId :: Property+prop_fromToPtrId = $(testWithTypes 'fromToPtrId ''SingleVarTypes)++prop_readWriteBytesId :: Property+prop_readWriteBytesId = $(testWithTypes 'readWriteBytesId ''SingleVarTypes)++prop_readWriteArrayId :: Property+prop_readWriteArrayId = $(testWithTypes 'readWriteArrayId ''SingleVarTypes)++prop_mixedTransformsId :: Property+prop_mixedTransformsId = $(testWithTypes 'mixedTransformsId ''SingleVarTypes)++prop_samePrimRepId :: Property+prop_samePrimRepId = $(testWithTypes 'samePrimRepId ''SamePrimRepTypes)++prop_vertexFields :: Property+prop_vertexFields = $(testWithTypes 'vertexFields ''TypeTriples)+++return [] -- this is for $forAllProperties+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
+ test/Numeric/QuaterDoubleTest.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TemplateHaskell #-}+module Numeric.QuaterDoubleTest (runTests) where++import Numeric.DataFrame.Arbitraries ()+import Numeric.Quaternion+import Numeric.Scalar+import Numeric.Vector+import Test.QuickCheck++type T = Double++eps :: T+eps = 1e-7++-- | Some non-linear function are very unstable;+-- it would be a downting task to determine the uncertainty precisely.+-- Instead, I just make sure the numbers are not so big to find at least+-- the most obvious bugs.+smaller :: Quater T -> Quater T+smaller q@(Quater x y z w)+ = if square q >= 1 then Quater (f x) (f y) (f z) (f w) else q+ where+ f :: T -> T+ f a | abs a > 2 = signum a * log (abs a)+ | otherwise = a++(=~=) :: Quater T -> Quater T -> Property+(=~=) = approxEq eps+infix 4 =~=++-- Even lower precision - for naturally fragile operations+approxEq :: T -> Quater T -> Quater T -> Property+approxEq e a b = property $ err <= c * scalar e+ where+ v1 = toVec4 a+ v2 = toVec4 b+ c = 1 `max` normL1 v1 `max` normL1 v2+ err = normL1 $ v1 - v2++prop_Eq :: Quater T -> Bool+prop_Eq q = and+ [ q == q+ , Quater (takei q) (takej q) (takek q) (taker q) == q+ , fromVecNum (imVec q) (taker q) == q+ , im q + re q == q+ , fromVec4 (toVec4 q) == q+ ]++prop_DoubleConjugate :: Quater T -> Property+prop_DoubleConjugate q = property $ conjugate (conjugate q) == q++prop_Square :: Quater T -> Property+prop_Square q = q * conjugate q =~= realToFrac (square q)++prop_RotScale :: Quater T -> Vector T 3 -> Property+prop_RotScale q v = fromVecNum (rotScale q v) 0 =~= q * fromVecNum v 0 * conjugate q++prop_GetRotScale :: Vector T 3 -> Vector T 3 -> Property+prop_GetRotScale a b+ = a /= 0 ==> approxEq eps' (fromVecNum (rotScale q a) 0) (fromVecNum b 0)+ where+ q = getRotScale a b+ -- when a and b are almost opposite, precision of getRotScale suffers a lot+ -- compensate it by increasing eps:+ eps' = if cross a b == 0+ then eps+ else eps / (max eps . min 1 . unScalar $+ 1 + normalized a `dot` normalized b)++prop_InverseRotScale :: Quater T -> Vector T 3 -> Property+prop_InverseRotScale q v+ = square q > eps ==> fromVecNum (rotScale (1/q) (rotScale q v)) 0 =~= fromVecNum v 0++prop_NegateToMatrix33 :: Quater T -> Bool+prop_NegateToMatrix33 q = toMatrix33 q == toMatrix33 (negate q)++prop_NegateToMatrix44 :: Quater T -> Bool+prop_NegateToMatrix44 q = toMatrix44 q == toMatrix44 (negate q)++prop_FromToMatrix33 :: Quater T -> Property+prop_FromToMatrix33 q+ = q /= 0 ==> fromMatrix33 (toMatrix33 q) =~= q+ .||. fromMatrix33 (toMatrix33 q) =~= negate q++prop_FromToMatrix44 :: Quater T -> Property+prop_FromToMatrix44 q+ = q /= 0 ==> fromMatrix44 (toMatrix44 q) =~= q+ .||. fromMatrix44 (toMatrix44 q) =~= negate q+++prop_RotationArg :: Quater T -> Property+prop_RotationArg q | q == 0 = axisRotation (imVec q) (qArg q) =~= 1+ | otherwise = axisRotation (imVec q) (qArg q) =~= signum q++prop_UnitQ :: Quater T -> Property+prop_UnitQ q+ = square q > eps ==> realToFrac (square (q / q)) =~= 1+++prop_ExpLog :: Quater T -> Property+prop_ExpLog q | square q < eps = log (exp q) =~= q+ | otherwise = exp (log q) =~= q++prop_SinAsin :: Quater T -> Property+prop_SinAsin q = sin (asin q') =~= q'+ where+ q' = signum q++prop_CosAcos :: Quater T -> Property+prop_CosAcos q = cos (acos q') =~= q'+ where+ q' = signum q++prop_TanAtan :: Quater T -> Property+prop_TanAtan q = tan (atan q') =~= q'+ where+ q' = sqrt (smaller q) -- because this inverse fun is fragile++prop_SinhAsinh :: Quater T -> Property+prop_SinhAsinh q = sinh (asinh q') =~= q'+ where+ q' = sqrt (smaller q) -- because this inverse fun is fragile++prop_CoshAcosh :: Quater T -> Property+prop_CoshAcosh q = cosh (acosh q) =~= q++prop_TanhAtanh :: Quater T -> Property+prop_TanhAtanh q = tanh (atanh q') =~= q'+ where+ q' = sqrt (smaller q) -- because this inverse fun is fragile++prop_SqrtSqr :: Quater T -> Property+prop_SqrtSqr q = sqrt q * sqrt q =~= q++prop_SinCos :: Quater T -> Property+prop_SinCos q = sin q' * sin q' + cos q' * cos q' =~= 1+ where+ q' = sqrt (smaller q) -- because it involves exponents++prop_SinhCosh :: Quater T -> Property+prop_SinhCosh q = cosh q' * cosh q' - sinh q' * sinh q' =~= 1+ where+ q' = sqrt (smaller q) -- because it involves exponents++prop_ReadShow :: Quater T -> Bool+prop_ReadShow q = q == read (show q)++return []+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
+ test/Numeric/QuaterFloatTest.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TemplateHaskell #-}+module Numeric.QuaterFloatTest (runTests) where++import Numeric.DataFrame.Arbitraries ()+import Numeric.Quaternion+import Numeric.Scalar+import Numeric.Vector+import Test.QuickCheck++type T = Float++eps :: T+eps = 1e-3++-- | Some non-linear function are very unstable;+-- it would be a downting task to determine the uncertainty precisely.+-- Instead, I just make sure the numbers are not so big to find at least+-- the most obvious bugs.+smaller :: Quater T -> Quater T+smaller q@(Quater x y z w)+ = if square q >= 1 then Quater (f x) (f y) (f z) (f w) else q+ where+ f :: T -> T+ f a | abs a > 2 = signum a * log (abs a)+ | otherwise = a++(=~=) :: Quater T -> Quater T -> Property+(=~=) = approxEq eps+infix 4 =~=++-- Even lower precision - for naturally fragile operations+approxEq :: T -> Quater T -> Quater T -> Property+approxEq e a b = property $ err <= c * scalar e+ where+ v1 = toVec4 a+ v2 = toVec4 b+ c = 1 `max` normL1 v1 `max` normL1 v2+ err = normL1 $ v1 - v2++prop_Eq :: Quater T -> Bool+prop_Eq q = and+ [ q == q+ , Quater (takei q) (takej q) (takek q) (taker q) == q+ , fromVecNum (imVec q) (taker q) == q+ , im q + re q == q+ , fromVec4 (toVec4 q) == q+ ]++prop_DoubleConjugate :: Quater T -> Property+prop_DoubleConjugate q = property $ conjugate (conjugate q) == q++prop_Square :: Quater T -> Property+prop_Square q = q * conjugate q =~= realToFrac (square q)++prop_RotScale :: Quater T -> Vector T 3 -> Property+prop_RotScale q v = fromVecNum (rotScale q v) 0 =~= q * fromVecNum v 0 * conjugate q++prop_GetRotScale :: Vector T 3 -> Vector T 3 -> Property+prop_GetRotScale a b+ = a /= 0 ==> approxEq eps' (fromVecNum (rotScale q a) 0) (fromVecNum b 0)+ where+ q = getRotScale a b+ -- when a and b are almost opposite, precision of getRotScale suffers a lot+ -- compensate it by increasing eps:+ eps' = if cross a b == 0+ then eps+ else eps / (max eps . min 1 . unScalar $+ 1 + normalized a `dot` normalized b)++prop_InverseRotScale :: Quater T -> Vector T 3 -> Property+prop_InverseRotScale q v+ = square q > eps ==> fromVecNum (rotScale (1/q) (rotScale q v)) 0 =~= fromVecNum v 0++prop_NegateToMatrix33 :: Quater T -> Bool+prop_NegateToMatrix33 q = toMatrix33 q == toMatrix33 (negate q)++prop_NegateToMatrix44 :: Quater T -> Bool+prop_NegateToMatrix44 q = toMatrix44 q == toMatrix44 (negate q)++prop_FromToMatrix33 :: Quater T -> Property+prop_FromToMatrix33 q+ = q /= 0 ==> fromMatrix33 (toMatrix33 q) =~= q+ .||. fromMatrix33 (toMatrix33 q) =~= negate q++prop_FromToMatrix44 :: Quater T -> Property+prop_FromToMatrix44 q+ = q /= 0 ==> fromMatrix44 (toMatrix44 q) =~= q+ .||. fromMatrix44 (toMatrix44 q) =~= negate q+++prop_RotationArg :: Quater T -> Property+prop_RotationArg q | q == 0 = axisRotation (imVec q) (qArg q) =~= 1+ | otherwise = axisRotation (imVec q) (qArg q) =~= signum q++prop_UnitQ :: Quater T -> Property+prop_UnitQ q+ = square q > eps ==> realToFrac (square (q / q)) =~= 1+++prop_ExpLog :: Quater T -> Property+prop_ExpLog q | square q < eps = log (exp q) =~= q+ | otherwise = exp (log q) =~= q++prop_SinAsin :: Quater T -> Property+prop_SinAsin q = sin (asin q') =~= q'+ where+ q' = signum q++prop_CosAcos :: Quater T -> Property+prop_CosAcos q = cos (acos q') =~= q'+ where+ q' = signum q++prop_TanAtan :: Quater T -> Property+prop_TanAtan q = tan (atan q') =~= q'+ where+ q' = sqrt (smaller q) -- because this inverse fun is fragile++prop_SinhAsinh :: Quater T -> Property+prop_SinhAsinh q = sinh (asinh q') =~= q'+ where+ q' = sqrt (smaller q) -- because this inverse fun is fragile++prop_CoshAcosh :: Quater T -> Property+prop_CoshAcosh q = cosh (acosh q) =~= q++prop_TanhAtanh :: Quater T -> Property+prop_TanhAtanh q = tanh (atanh q') =~= q'+ where+ q' = sqrt (smaller q) -- because this inverse fun is fragile++prop_SqrtSqr :: Quater T -> Property+prop_SqrtSqr q = sqrt q * sqrt q =~= q++prop_SinCos :: Quater T -> Property+prop_SinCos q = sin q' * sin q' + cos q' * cos q' =~= 1+ where+ q' = sqrt (smaller q) -- because it involves exponents++prop_SinhCosh :: Quater T -> Property+prop_SinhCosh q = cosh q' * cosh q' - sinh q' * sinh q' =~= 1+ where+ q' = sqrt (smaller q) -- because it involves exponents++prop_ReadShow :: Quater T -> Bool+prop_ReadShow q = q == read (show q)++return []+runTests :: Int -> IO Bool+runTests n = $forAllProperties+ $ quickCheckWithResult stdArgs { maxSuccess = n }
− test/Numeric/QuaternionTest.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Numeric.QuaternionTest (runTests) where--import Test.QuickCheck-import Numeric.Quaternion-import Numeric.Vector---instance (Quaternion t, Arbitrary t) => Arbitrary (Quater t) where- arbitrary = packQ <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary- shrink q | (x,y,z,t) <- unpackQ q = packQ <$> shrink x <*> shrink y <*> shrink z <*> shrink t--instance Arbitrary Vec3d where- arbitrary = vec3 <$> arbitrary <*> arbitrary <*> arbitrary- shrink v | (x,y,z) <- unpackV3 v = vec3 <$> shrink x <*> shrink y <*> shrink z---(=~=) :: (Quaternion a, Num a, Ord a, Num (Quater a), Fractional a) => Quater a -> Quater a -> Bool-(=~=) a b = taker (abs (a - b)) <= eps- where- s = max 1e-6 $ max (taker (abs a)) (taker (abs b))- eps = s * 1e-6-infix 4 =~=---prop_Eq :: QDouble -> Bool-prop_Eq q = and- [ (\(x,y,z,t) -> packQ x y z t) (unpackQ q) == q- , packQ (takei q) (takej q) (takek q) (taker q) == q- , fromVecNum (imVec q) (taker q) == q- , im q + re q == q- ]---prop_DoubleConjugate :: QDouble -> Bool-prop_DoubleConjugate q = conjugate (conjugate q) == q--prop_Square :: QDouble -> Bool-prop_Square q = q * conjugate q =~= realToFrac (square q)---prop_RotScale :: QDouble -> Vec3d -> Bool-prop_RotScale q v = fromVecNum (rotScale q v) 0 =~= q * fromVecNum v 0 * conjugate q--prop_GetRotScale :: Vec3d -> Vec3d -> Bool-prop_GetRotScale a b = fromVecNum (rotScale q a) 0 =~= fromVecNum b 0- where- q = getRotScale a b---prop_InverseRotScale :: QDouble -> Vec3d -> Bool-prop_InverseRotScale q v | q /= 0 = fromVecNum (rotScale (1/q) (rotScale q v)) 0 =~= fromVecNum v 0- | otherwise = True--prop_FromToMatrix33 :: QDouble -> Bool-prop_FromToMatrix33 q | q == 0 = True- | otherwise = fromMatrix33 (toMatrix33 (signum q)) =~= signum q * signum (re q)--prop_FromToMatrix44 :: QDouble -> Bool-prop_FromToMatrix44 q | q == 0 = True- | otherwise = fromMatrix44 (toMatrix44 (signum q)) =~= signum q * signum (re q)--prop_RotationArg :: QDouble -> Bool-prop_RotationArg q | q == 0 = axisRotation (imVec q) (qArg q) =~= 1- | otherwise = axisRotation (imVec q) (qArg q) =~= signum q---prop_UnitQ :: QDouble -> Bool-prop_UnitQ q | q == 0 = True- | otherwise = realToFrac (square (q / q)) =~= (1 :: QDouble)---prop_ExpLog :: QDouble -> Bool-prop_ExpLog q | q == 0 = log (exp q) == q- | otherwise = exp (log q) =~= q--prop_SinAsin :: QDouble -> Bool-prop_SinAsin q = sin (asin q') =~= q'- where- q' = signum q--prop_CosAcos :: QDouble -> Bool-prop_CosAcos q = cos (acos q') =~= q'- where- q' = signum q--prop_TanAtan :: QDouble -> Bool-prop_TanAtan q = tan (atan q') =~= q'- where -- protect agains big numbers and rounding errors- q' = if square q >= 1e6 then signum q else q---prop_SinhAsinh :: QDouble -> Bool-prop_SinhAsinh q = sinh (asinh q') =~= q'- where -- protect agains big numbers and rounding errors- q' = if square q >= 1e6 then signum q else q--prop_CoshAcosh :: QDouble -> Bool-prop_CoshAcosh q = cosh (acosh q') =~= q'- where -- protect agains big numbers and rounding errors- q' = if square q >= 1e6 then signum q else q--prop_TanhAtanh :: QDouble -> Bool-prop_TanhAtanh q = tanh (atanh q') =~= q'- where -- protect agains big numbers and rounding errors- q' = if square q >= 1e6 then signum q else q--prop_SinCos :: QDouble -> Bool-prop_SinCos q = sin q' * sin q' + cos q' * cos q' =~= 1- where- q' = signum q--prop_SinhCosh :: QDouble -> Bool-prop_SinhCosh q = cosh q' * cosh q' - sinh q' * sinh q' =~= 1- where- q' = signum q--return []-runTests :: IO Bool-runTests = $quickCheckAll
test/Spec.hs view
@@ -1,24 +1,30 @@ module Main (tests, main) where -import Distribution.TestSuite-import System.Exit+import Distribution.TestSuite+import System.Exit import qualified Numeric.DataFrame.BasicTest import qualified Numeric.DataFrame.SubSpaceTest import qualified Numeric.MatrixDoubleTest import qualified Numeric.MatrixFloatTest-import qualified Numeric.QuaternionTest+import qualified Numeric.PrimBytesTest+import qualified Numeric.QuaterDoubleTest+import qualified Numeric.QuaterFloatTest -- | Collection of tests in detailed-0.9 format tests :: IO [Test] tests = return- [ test "DataFrame.Basic" Numeric.DataFrame.BasicTest.runTests- , test "DataFrame.SubSpace" Numeric.DataFrame.SubSpaceTest.runTests- , test "MatrixDouble" Numeric.MatrixDoubleTest.runTests- , test "MatrixFloat" Numeric.MatrixFloatTest.runTests- , test "Quaternion" Numeric.QuaternionTest.runTests+ [ test "DataFrame.Basic" $ Numeric.DataFrame.BasicTest.runTests n+ , test "DataFrame.SubSpace" $ Numeric.DataFrame.SubSpaceTest.runTests n+ , test "MatrixDouble" $ Numeric.MatrixDoubleTest.runTests n+ , test "MatrixFloat" $ Numeric.MatrixFloatTest.runTests n+ , test "QuaterDouble" $ Numeric.QuaterDoubleTest.runTests n+ , test "QuaterFloat" $ Numeric.QuaterFloatTest.runTests n+ , test "PrimBytes" $ Numeric.PrimBytesTest.runTests n ]+ where+ n = 1000 :: Int @@ -26,16 +32,17 @@ -- | Run tests as exitcode-stdio-1.0 main :: IO () main = do+ putStrLn "" ts <- tests- trs <- mapM (\(Test ti) ->(,) (name ti) <$> run ti) ts- case filter (not . isGood) trs of+ trs <- mapM (\(Test ti) -> (,) (name ti) <$> run ti) ts+ case filter (not . isGood . snd) trs of [] -> exitSuccess xs -> do putStrLn $ "Failed tests: " ++ unwords (fmap fst xs) exitFailure where- isGood (_, Finished Pass) = True- isGood _ = False+ isGood (Finished Pass) = True+ isGood _ = False -- | Convert QuickCheck props into Cabal tests
+ test/Spec/Util.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Spec.Util (propWithTypes, testWithTypes) where++import Control.Applicative+import Control.Monad+import Data.Monoid+import Language.Haskell.TH+import Test.QuickCheck+-- import Language.Haskell.TH.Syntax++-- | Test a property with several types.+--+-- The first argument is the name of a @Testable@ function+--+-- The second argument is expected to be a type synonym of kind [k] --+-- the variants of type arguments to apply to a fun+--+-- Kind @k@ here should match the kind of type variable of the testable function,+-- (or a promoted n-tuple or a promoted list of such variables.)+testWithTypes :: Name -- ^ Function with a few type variables+ -> Name -- ^ Name of a type with kind [k]+ -> ExpQ+testWithTypes fName tyNames = do+ typeLists <- getTypes tyNames+ let props = (\ts -> mkProp ts $ foldl AppTypeE (VarE fName) ts) <$> typeLists+ [e| conjoin $(listE props) |]+ where+ mkProp :: [Type] -> Exp -> ExpQ+ mkProp ts ex+ = let qe = pure ex :: ExpQ+ qs = litE . stringL $ unlines ["Tested with types:", pprint ts]+ in [e| property ( counterexample $qs $qe ) |]++-- | Assuming the argument is a type synonym for a list of types, unpack it.+getTypes :: Name -> Q [[Type]]+getTypes tyNames =+ reify tyNames >>= unpackTyConI >>= unpackFamList >>= traverse unpackAppType+ where+ unpackTyConI :: Info -> Q Type+ unpackTyConI (TyConI (TySynD _ [] t)) = pure t+ unpackTyConI i = error $+ "getTypes/unpackTyConI:"+ ++ "Expected a type synonym with no arguments, but got something else "+ ++ show i+ unpackFamList :: Type -> Q [Type]+ unpackFamList t+ | Just ts <- unpackPList t = pure ts+ | otherwise = error $+ "getTypes/unpackFamList:"+ ++ "Expected a promoted (type) list inside the type synonym, but got "+ ++ show t+ unpackAppType :: Type -> Q [Type]+ unpackAppType t+ | Just ts <- unpackPList t = pure ts+ | Just ts <- unpackPTuple t = pure ts+ | otherwise = pure [t]+ unpackPTuple :: Type -> Maybe [Type]+ unpackPTuple (PromotedTupleT _) = pure []+ unpackPTuple (AppT t r) = (++ [r]) <$> unpackPTuple t+ unpackPTuple (ParensT t) = unpackPTuple t+ unpackPTuple (SigT t _) = unpackPTuple t+ unpackPTuple _ = Nothing+ unpackPList :: Type -> Maybe [Type]+ unpackPList PromotedNilT = pure []+ unpackPList (AppT (AppT PromotedConsT r) t) = (r:) <$> unpackPList t+ unpackPList (ParensT t) = unpackPList t+ unpackPList (SigT t _) = unpackPList t+ unpackPList _ = Nothing+++-- | Make several properties by applying types+propWithTypes :: Name -- ^ Function with a few type variables+ -> [[Name]] -- ^ All specific types to test it on.+ -> DecsQ+propWithTypes fName tyNames+ = fmap join . sequence+ $ zipWith3 mkDecl funNames funTypes appliedExpressions+ where+ appliedExpressions :: [ExpQ]+ appliedExpressions+ = foldl (\e -> appTypeE e . conT) (varE fName) <$> tyNames+ funNames :: [Q Name]+ funNames+ = newName . foldl (\n -> (n ++) . nameBase) ("prop_" ++ nameBase fName) <$> tyNames+ funTypes :: [TypeQ]+ funTypes+ = (\ns -> fmap (subtTyVars (map ConT ns)) ) <$> tyNames <*> [infoType <$> reify fName]+ mkDecl qn qt qe = do+ n <- qn+ sequence+ [ sigD n qt+ , funD n [(\e -> Clause [] (NormalB e) []) <$> qe]+ ]+++-- | Get a type of something at the term level (e.g. function, var, constructor).+infoType :: Info -> Type+infoType (ClassOpI _ t _) = t+infoType (DataConI _ t _) = t+infoType (VarI _ t _) = t+infoType _ = undefined++-- | Substitute at most as many type variables as given types in the list.+--+-- For every type in a list @ts@, the function looks for the first occurrence+-- of any type variable and substitutes all its occurrences in the target type.+--+-- Returns the original type if it has no type variables.+subtTyVars :: [Type] -> Type -> Type+subtTyVars = flip (foldl f)+ where+ f t x+ | Just v <- findFirstTyVar t+ = substTyVar v x t+ | otherwise = t++-- | Substitute all occurrences of a type variable+substTyVar :: Name -- ^ TyVar name+ -> Type -- ^ Substitution+ -> Type -- ^ Original type+ -> Type+substTyVar x y (ForallT vs ctx t)+ = ForallT (remVar vs) (ctx >>= substOrRemove) (substTyVar x y t)+ where+ thisVar :: TyVarBndr -> Bool+ thisVar (PlainTV n) = n == x+ thisVar (KindedTV n _) = n == x+ remVar :: [TyVarBndr] -> [TyVarBndr]+ remVar = filter (not . thisVar)+ substOrRemove p+ = let p' = substTyVar x y p+ in if findFirstTyVar p' == Nothing then [] else [p]+substTyVar x y (AppT t1 t2) = AppT (substTyVar x y t1) (substTyVar x y t2)+substTyVar x y (SigT t1 t2) = SigT (substTyVar x y t1) (substTyVar x y t2)+substTyVar x y v@(VarT n) = if n == x then y else v+substTyVar x y (InfixT t1 n t2) = InfixT (substTyVar x y t1) n (substTyVar x y t2)+substTyVar x y (UInfixT t1 n t2) = UInfixT (substTyVar x y t1) n (substTyVar x y t2)+substTyVar x y (ParensT t) = ParensT (substTyVar x y t)+substTyVar _ _ t = t++findFirstTyVar :: Type -> Maybe Name+findFirstTyVar (ForallT (PlainTV n:_) _ _) = Just n+findFirstTyVar (ForallT (KindedTV n _:_) _ _) = Just n+findFirstTyVar (ForallT [] ctx t)+ = getFirst (foldMap (First . findFirstTyVar) ctx) <|> findFirstTyVar t+findFirstTyVar (AppT t1 t2) = findFirstTyVar t1 <|> findFirstTyVar t2+findFirstTyVar (SigT t1 k1) = findFirstTyVar t1 <|> findFirstTyVar k1+findFirstTyVar (VarT n) = Just n+findFirstTyVar (InfixT t1 _ t2) = findFirstTyVar t1 <|> findFirstTyVar t2+findFirstTyVar (UInfixT t1 _ t2) = findFirstTyVar t1 <|> findFirstTyVar t2+findFirstTyVar (ParensT t) = findFirstTyVar t+findFirstTyVar _ = Nothing