numhask-array-0.1.0.0: src/NumHask/Accelerate.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- | safe-typed n-dimensional arrays with Accelerate arrays under the hood
module NumHask.Accelerate where
import Data.Array.Accelerate.Array.Sugar (listToShape)
import Data.Array.Accelerate.LLVM.Native (run)
import Data.Singletons
import Data.Singletons.TypeLits
import GHC.Exts
import GHC.Show
import NumHask.Prelude hiding (All, Map)
import NumHask.Shape
import qualified Data.Array.Accelerate as A
type family NatsToShape (ns :: [Nat]) where
NatsToShape '[] = A.Z
NatsToShape (x:xs) = NatsToShape xs A.:. Int
-- $setup
-- >>> :set -XDataKinds
-- >>> :set -XOverloadedLists
-- >>> :set -XTypeFamilies
-- >>> let a = [1..24] :: ArrayAcc '[2,3,4] Int
-- >>> let v = [1,2,3] :: ArrayAcc '[3] Int
-- >>> a
-- Array (Z :. 4 :. 3 :. 2) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
newtype ArrayAcc (r :: [Nat]) a = ArrayAcc (A.Acc (A.Array (NatsToShape r) a))
instance forall (r :: [Nat]). (SingI r) => HasShape (ArrayAcc r) where
type Shape (ArrayAcc r) = [Int]
shape _ = fmap fromIntegral (fromSing (sing :: Sing r))
instance
( SingI r
, Num a
, A.Elt a
, A.Shape (NatsToShape r)
) => IsList (ArrayAcc (r :: [Nat]) a) where
type Item (ArrayAcc r a) = a
fromList l = ArrayAcc $ A.use $ A.fromList (listToShape sh) l
where
sh = fmap fromIntegral (fromSing (sing :: Sing r))
toList (ArrayAcc a) = A.toList $ run a
instance
( Show a
, A.Elt a
, SingI r
, A.Shape (NatsToShape r)
) => Show (ArrayAcc r a) where
show (ArrayAcc l) = GHC.Show.show $ run l
instance
( Eq a
, A.Elt a
, SingI r
, A.Shape (NatsToShape r)
, Eq (NatsToShape r)
) => Eq (ArrayAcc r a) where
(==) (ArrayAcc a) (ArrayAcc b) = run a == run b
bin :: (A.Elt a, A.Shape (NatsToShape r)) =>
(A.Exp a -> A.Exp a -> A.Exp a) -> ArrayAcc r a -> ArrayAcc r a -> ArrayAcc r a
bin f (ArrayAcc a) (ArrayAcc b) = ArrayAcc (A.zipWith f a b)
{-
singleton ::
( SingI r
, A.Elt a
, Num a
, A.Shape (NatsToShape r)
) => [a] -> ArrayAcc (r :: [Nat]) a
singleton a = ArrayAcc $ A.use $ A.fromList (listToShape sh) a
where
sh = fmap fromIntegral (fromSing (sing :: Sing r))
-}
-- Exp additive instances
instance
( A.Num a
, AdditiveMagma a) =>
AdditiveMagma (A.Exp a) where
plus = (A.+)
instance
( A.Num a
, AdditiveUnital a) =>
AdditiveUnital (A.Exp a) where
zero = A.constant zero
instance
( A.Num a
, AdditiveAssociative a) =>
AdditiveAssociative (A.Exp a)
instance
( A.Num a
, AdditiveCommutative a) =>
AdditiveCommutative (A.Exp a)
instance
( A.Num a
, Additive a) =>
Additive (A.Exp a)
instance
( A.Num a
, AdditiveInvertible a) =>
AdditiveInvertible (A.Exp a) where
negate = A.negate
instance
( A.Num a
, AdditiveGroup a) =>
AdditiveGroup (A.Exp a)
-- Exp multiplivcative instances
instance
( A.Num a
, MultiplicativeMagma a) =>
MultiplicativeMagma (A.Exp a) where
times = (A.*)
instance
( A.Num a
, MultiplicativeUnital a) =>
MultiplicativeUnital (A.Exp a) where
one = A.constant one
instance
( A.Num a
, MultiplicativeAssociative a) =>
MultiplicativeAssociative (A.Exp a)
instance
( A.Num a
, MultiplicativeCommutative a) =>
MultiplicativeCommutative (A.Exp a)
instance
( A.Num a
, Multiplicative a) =>
Multiplicative (A.Exp a)
instance
( A.Num a
, Fractional (A.Exp a)
, MultiplicativeInvertible a) =>
MultiplicativeInvertible (A.Exp a) where
recip = A.recip
instance
( A.Num a
, Fractional (A.Exp a)
, MultiplicativeGroup a) =>
MultiplicativeGroup (A.Exp a)
-- ArrayAcc additive instances
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, AdditiveMagma a
) =>
AdditiveMagma (ArrayAcc r a) where
plus = bin plus
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, AdditiveUnital a
) =>
AdditiveUnital (ArrayAcc r a) where
zero = ArrayAcc $ A.use (A.fromList (listToShape sh) (repeat zero))
where
sh = fmap fromIntegral (fromSing (sing :: Sing r))
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, AdditiveAssociative a
) =>
AdditiveAssociative (ArrayAcc r a)
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, AdditiveCommutative a
) =>
AdditiveCommutative (ArrayAcc r a)
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, Additive a
) =>
Additive (ArrayAcc r a)
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, AdditiveInvertible a
) =>
AdditiveInvertible (ArrayAcc r a) where
negate (ArrayAcc a) = ArrayAcc $ A.map A.negate a
instance
( A.Shape (NatsToShape r)
, SingI r
, A.Num a
, AdditiveGroup a
) =>
AdditiveGroup (ArrayAcc r a)
-- $additive tests
-- >>> let m = [0..] :: ArrayAcc '[2,3] Int
-- >>> m
-- Array (Z :. 3 :. 2) [0,1,2,3,4,5]
--
-- >>> m+zero
-- Array (Z :. 3 :. 2) [0,1,2,3,4,5]
--
-- >>> m+m
-- Array (Z :. 3 :. 2) [0,2,4,6,8,10]
--
-- >>> m-m == zero
-- True