trexio-hs-0.1.0: src/TREXIO/CooArray.hs
{-# LANGUAGE UndecidableInstances #-}
{- |
Module: TREXIO.CooArray
Description: Coordinate list sparse array representation for TREXIO
Copyright: Phillip Seeber 2024
License: BSD-3-Clause
Maintainer: phillip.seeber@uni-jena.de
Stability: experimental
Portability: POSIX
-}
module TREXIO.CooArray (
CooArray,
values,
coords,
cooSize,
mkCooArrayF,
mkCooArray,
)
where
import Data.Foldable
import Data.Massiv.Array as Massiv hiding (all, toList)
import GHC.Generics (Generic)
-- | A coordinate list array representation.
data CooArray r ix a = CooArray
{ values_ :: Vector r a
, coords_ :: Vector r ix
, cooSize_ :: Sz ix
-- ^ Size of the COO array
}
deriving (Generic)
instance (Eq (Vector r a), Eq (Vector r ix), Eq ix) => Eq (CooArray r ix a) where
CooArray v1 c1 s1 == CooArray v2 c2 s2 = v1 == v2 && c1 == c2 && s1 == s2
instance (Ord (Vector r a), Ord (Vector r ix), Ord ix) => Ord (CooArray r ix a) where
compare (CooArray v1 c1 s1) (CooArray v2 c2 s2) =
compare v1 v2 <> compare c1 c2 <> compare s1 s2
instance
(Show (Vector r a), Show (Vector r ix), Index ix, Show ix) =>
Show (CooArray r ix a)
where
show CooArray{..} =
"CooArray "
<> show values_
<> " "
<> show coords_
<> " "
<> show cooSize_
values :: CooArray r ix a -> Vector r a
values CooArray{values_} = values_
coords :: CooArray r ix a -> Vector r ix
coords CooArray{coords_} = coords_
cooSize :: CooArray r ix a -> Sz ix
cooSize CooArray{cooSize_} = cooSize_
-- | Make a 'CooArray' from a list of coordinate-value pairs.
mkCooArrayF ::
(Foldable f, Index ix, Manifest r a, Manifest r ix, MonadThrow m, Stream r Ix1 ix) =>
Sz ix ->
f (ix, a) ->
m (CooArray r ix a)
mkCooArrayF cooSize_ coo
| isNull unsafeInds = return CooArray{..}
| otherwise = throwM $ IndexOutOfBoundsException cooSize_ (shead' unsafeInds)
where
arr = Massiv.fromList @B Par . toList $ coo
values_ = Massiv.compute . Massiv.map snd $ arr
coords_ = Massiv.compute . Massiv.map fst $ arr
unsafeInds = Massiv.sfilter (not . isSafeIndex cooSize_) coords_
-- | Make a 'CooArray' from a indices and values.
mkCooArray ::
(MonadThrow m, Index ix, Size r, Stream r Ix1 ix) =>
Sz ix ->
Vector r ix ->
Vector r a ->
m (CooArray r ix a)
mkCooArray cooSize_ coords_ values_
| Massiv.size coords_ /= Massiv.size values_ = throwM $ SizeMismatchException (Massiv.size coords_) (Massiv.size values_)
| not . isNull $ unsafeInds = throwM $ IndexOutOfBoundsException cooSize_ (shead' unsafeInds)
| otherwise = return CooArray{..}
where
unsafeInds = Massiv.sfilter (not . isSafeIndex cooSize_) coords_