numhask-array 0.10.2 → 0.11.0.0
raw patch · 8 files changed
+325/−186 lines, 8 filesdep −QuickCheckdep ~basedep ~numhasksetup-changed
Dependencies removed: QuickCheck
Dependency ranges changed: base, numhask
Files
- ChangeLog.md +7/−0
- Setup.hs +0/−3
- numhask-array.cabal +77/−25
- src/NumHask/Array.hs +1/−19
- src/NumHask/Array/Dynamic.hs +97/−13
- src/NumHask/Array/Fixed.hs +138/−105
- src/NumHask/Array/Shape.hs +5/−13
- test/doctests.hs +0/−8
ChangeLog.md view
@@ -1,3 +1,10 @@+0.11.0.0+===++* new operators: indices, sequent, takes, undiag+* Divisive instance for Array+* inverse machinery: chol, invtri+ 0.9.2 == * fixes for numhask-0.9
− Setup.hs
@@ -1,3 +0,0 @@-import Distribution.Simple--main = defaultMain
numhask-array.cabal view
@@ -1,6 +1,6 @@-cabal-version: 2.4+cabal-version: 3.0 name: numhask-array-version: 0.10.2+version: 0.11.0.0 synopsis: Multi-dimensional arrays. description: This package provides an interface into the [numhask](https://hackage.haskell.org/package/numhask) API, and both type- and value-level shape manipulation routines.@@ -25,41 +25,93 @@ copyright: Tony Day license: BSD-3-Clause license-file: LICENSE-tested-with: GHC ==8.8.4 || ==8.10.7 || ==9.2.5 || ==9.4.4+tested-with: GHC == 8.10.7 || ==9.2.8 || ==9.4.5 || ==9.6.2 build-type: Simple-extra-source-files: ChangeLog.md+extra-doc-files: ChangeLog.md source-repository head type: git location: https://github.com/tonyday567/numhask-array -library- hs-source-dirs: src- default-extensions:+common ghc2021-stanza+ if impl(ghc >=9.2)+ default-language:+ GHC2021+ if impl(ghc <9.2)+ default-language:+ Haskell2010+ default-extensions:+ BangPatterns+ BinaryLiterals+ ConstrainedClassMethods+ ConstraintKinds+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveLift+ DeriveTraversable+ DoAndIfThenElse+ EmptyCase+ EmptyDataDecls+ EmptyDataDeriving+ ExistentialQuantification+ ExplicitForAll+ FlexibleContexts+ FlexibleInstances+ ForeignFunctionInterface+ GADTSyntax+ GeneralisedNewtypeDeriving+ HexFloatLiterals+ ImplicitPrelude+ InstanceSigs+ KindSignatures+ MonomorphismRestriction+ MultiParamTypeClasses+ NamedFieldPuns+ NamedWildCards+ NumericUnderscores+ PatternGuards+ PolyKinds+ PostfixOperators+ RankNTypes+ RelaxedPolyRec+ ScopedTypeVariables+ StandaloneDeriving+ StarIsType+ TraditionalRecordSyntax+ TupleSections+ TypeApplications+ TypeOperators+ TypeSynonymInstances+ if impl(ghc <9.2) && impl(ghc >=8.10)+ default-extensions:+ ImportQualifiedPost+ StandaloneKindSignatures++common ghc-options-stanza ghc-options:- -Wall -Wcompat -Wincomplete-record-updates- -Wincomplete-uni-patterns -Wredundant-constraints+ -Wall+ -Wcompat+ -Wincomplete-record-updates+ -Wincomplete-uni-patterns+ -Wredundant-constraints+ -Widentities+ -Wpartial-fields +library+ import: ghc2021-stanza+ import: ghc-options-stanza+ hs-source-dirs: src build-depends:- , adjunctions >=4.0 && <5- , base >=4.11 && <5- , distributive >=0.4 && <0.7- , numhask ^>=0.10- , vector >=0.10 && <0.14+ , adjunctions >=4.0 && <5+ , base >=4.11 && <5+ , distributive >=0.4 && <0.7+ , numhask >=0.11 && < 0.12+ , vector >=0.10 && <0.14 exposed-modules: NumHask.Array NumHask.Array.Dynamic NumHask.Array.Fixed NumHask.Array.Shape-- default-language: Haskell2010--test-suite doctests- type: exitcode-stdio-1.0- main-is: doctests.hs- hs-source-dirs: test- default-language: Haskell2010- build-depends:- , base- , QuickCheck
src/NumHask/Array.hs view
@@ -1,6 +1,4 @@-{-# OPTIONS_GHC -Wall #-}---- | Multi-dimensional arrays for numhask.+-- | Multi-dimensional arrays module NumHask.Array ( -- * Imports -- $imports@@ -38,19 +36,3 @@ -- - provides operators at value and type level to help manipulate shapes. -- -- - provides fixed and dynamic arrays with the same API.------ === API of an array language------ See <http://hiperfit.dk/pdf/array14_final.pdf> for context and a sketch of an intermediate typed array language effort.------ The operators that result from using the 'Representable' type - separation of size tracking at compile level, from computational at runtime - ends up looking like [APL](https://en.wikipedia.org/wiki/APL_(programming_language\)).------ Matrix multiplication in APL is @+.x@ and in numhask-array is @dot sum (*)@. There is a slight increase in abstraction by explicitly exposing the fold in the algorithm, but the expressions are both very neat and abstracted away from the specialisation of multiplying matrices.------ References:------ <https://blog.plover.com/prog/apl-matrix-product.html>------ <https://en.wikipedia.org/wiki/Tensor_contraction>------ <https://en.wikipedia.org/wiki/Tensor_(intrinsic_definition)#Definition:_Tensor_Product_of_Vector_Spaces>
src/NumHask/Array/Dynamic.hs view
@@ -1,20 +1,11 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RebindableSyntax #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StrictData #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE NoStarIsType #-} {-# OPTIONS_GHC -Wno-redundant-constraints #-} {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-} {-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-} --- | Arrays with a dynamic shape.+-- | Arrays with a dynamic shape (shape only known at runtime). module NumHask.Array.Dynamic ( -- $usage Array (..),@@ -28,10 +19,14 @@ tabulate, -- * Operators+ takes, reshape, transpose,- diag,+ indices, ident,+ sequent,+ diag,+ undiag, singleton, selects, selectsExcept,@@ -45,6 +40,7 @@ append, reorder, expand,+ expandr, apply, contract, dot,@@ -70,7 +66,7 @@ where import Data.List (intercalate)-import qualified Data.Vector as V+import Data.Vector qualified as V import GHC.Show (Show (..)) import NumHask.Array.Shape import NumHask.Prelude as P hiding (product)@@ -170,6 +166,19 @@ tabulate :: () => [Int] -> ([Int] -> a) -> Array a tabulate ds f = Array ds . V.generate (size ds) $ (f . shapen ds) +-- | Takes the top-most elements according to the new dimension.+--+-- >>> takes [2,2,3] a+-- [[[1, 2, 3],+-- [5, 6, 7]],+-- [[13, 14, 15],+-- [17, 18, 19]]]+takes ::+ [Int] ->+ Array a ->+ Array a+takes ds a = tabulate ds $ \s -> index a s+ -- | Reshape an array (with the same number of elements). -- -- >>> reshape [4,3,2] a@@ -198,6 +207,15 @@ transpose :: Array a -> Array a transpose a = tabulate (reverse $ shape a) (index a . reverse) +-- | Indices of an Array.+--+-- >>> indices [3,3]+-- [[[0,0], [0,1], [0,2]],+-- [[1,0], [1,1], [1,2]],+-- [[2,0], [2,1], [2,2]]]+indices :: [Int] -> Array [Int]+indices ds = tabulate ds id+ -- | The identity array. -- -- >>> ident [3,2]@@ -212,6 +230,22 @@ isDiag [x, y] = x == y isDiag (x : y : xs) = x == y && isDiag (y : xs) +-- | An array of sequential Ints+--+-- >>> sequent [3]+-- [0, 1, 2]+--+-- >>> sequent [3,3]+-- [[0, 0, 0],+-- [0, 1, 0],+-- [0, 0, 2]]+sequent :: [Int] -> Array Int+sequent ds = tabulate ds go+ where+ go [] = zero+ go [i] = i+ go (i : js) = bool zero i (all (i ==) js)+ -- | Extract the diagonal of an array. -- -- >>> diag (ident [3,2])@@ -224,6 +258,21 @@ go [] = throw (NumHaskException "Rank Underflow") go (s' : _) = index a (replicate (rank (shape a)) s') +-- | Expand the array to form a diagonal array+--+-- >>> undiag 2 (fromFlatList [2] [1,1])+-- [[1, 0],+-- [0, 1]]+undiag ::+ (Additive a) =>+ Int ->+ Array a ->+ Array a+undiag r a = tabulate (replicate r (head (shape a))) go+ where+ go [] = throw (NumHaskException "Rank Underflow")+ go xs@(x : xs') = bool zero (index a xs) (all (x ==) xs')+ -- | Create an array composed of a single value. -- -- >>> singleton [3,2] one@@ -420,6 +469,19 @@ -- [[1, 2, 3], -- [2, 4, 6], -- [3, 6, 9]]+--+-- Alternatively, expand can be understood as representing the permutation of element pairs of two arrays, so like the Applicative List instance.+--+-- >>> i2 = indices [2,2]+-- >>> expand (,) i2 i2+-- [[[[([0,0],[0,0]), ([0,0],[0,1])],+-- [([0,0],[1,0]), ([0,0],[1,1])]],+-- [[([0,1],[0,0]), ([0,1],[0,1])],+-- [([0,1],[1,0]), ([0,1],[1,1])]]],+-- [[[([1,0],[0,0]), ([1,0],[0,1])],+-- [([1,0],[1,0]), ([1,0],[1,1])]],+-- [[([1,1],[0,0]), ([1,1],[0,1])],+-- [([1,1],[1,0]), ([1,1],[1,1])]]]] expand :: (a -> b -> c) -> Array a ->@@ -429,9 +491,29 @@ where r = rank (shape a) +-- | Like expand, but permutes the first array first, rather than the second.+--+-- >>> expand (,) v (fmap (+3) v)+-- [[(1,4), (1,5), (1,6)],+-- [(2,4), (2,5), (2,6)],+-- [(3,4), (3,5), (3,6)]]+--+-- >>> expandr (,) v (fmap (+3) v)+-- [[(1,4), (2,4), (3,4)],+-- [(1,5), (2,5), (3,5)],+-- [(1,6), (2,6), (3,6)]]+expandr ::+ (a -> b -> c) ->+ Array a ->+ Array b ->+ Array c+expandr f a b = tabulate ((++) (shape a) (shape b)) (\i -> f (index a (drop r i)) (index b (take r i)))+ where+ r = rank (shape a)+ -- | Apply an array of functions to each array of values. ----- This is in the spirit of the applicative functor operation (<*>).+-- This is in the spirit of the applicative functor operation (\<*\>). -- -- > expand f a b == apply (fmap f a) b --@@ -439,6 +521,8 @@ -- [[1, 2, 3], -- [2, 4, 6], -- [3, 6, 9]]+--+-- Dynamic arrays can't be Applicatives because there is no 'pure' (Shape is not known at compile-time). -- -- >>> let b = fromFlatList [2,3] [1..6] :: Array Int -- >>> contract sum [1,2] (apply (fmap (*) b) (transpose b))
src/NumHask/Array/Fixed.hs view
@@ -1,26 +1,13 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedLists #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RebindableSyntax #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StrictData #-}-{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE NoStarIsType #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} {-# OPTIONS_GHC -Wno-redundant-constraints #-} {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} --- | Arrays with a fixed shape.+-- | Arrays with a fixed shape (known shape at compile time). module NumHask.Array.Fixed ( -- $usage Array (..),@@ -34,10 +21,11 @@ takes, reshape, transpose,- diag,- undiag,+ indices, ident, sequent,+ diag,+ undiag, singleton, selects, selectsExcept,@@ -51,7 +39,7 @@ append, reorder, expand,- expand',+ expandr, apply, contract, dot,@@ -63,7 +51,6 @@ -- -- Scalar specialisations- Scalar, fromScalar, toScalar, @@ -85,7 +72,6 @@ safeRow, mmult, chol,- inv, invtri, ) where@@ -94,11 +80,11 @@ import Data.Functor.Rep import Data.List ((!!)) import Data.Proxy-import qualified Data.Vector as V+import Data.Vector qualified as V import GHC.Exts (IsList (..)) import GHC.Show (Show (..)) import GHC.TypeLits-import qualified NumHask.Array.Dynamic as D+import NumHask.Array.Dynamic qualified as D import NumHask.Array.Shape import NumHask.Prelude as P hiding (sequence, toList) @@ -115,6 +101,7 @@ -- >>> import Data.Functor.Rep -- >>> let s = [1] :: Array ('[] :: [Nat]) Int -- scalar -- >>> let v = [1,2,3] :: Array '[3] Int -- vector+-- >>> let t = [0..3] :: Array '[2,2] Int -- square matrix -- >>> let m = [0..11] :: Array '[3,4] Int -- matrix -- >>> let a = [1..24] :: Array '[2,3,4] Int @@ -146,6 +133,7 @@ -- -- >>> [1,2,3] :: Array '[2,2] Int -- *** Exception: NumHaskException {errorMessage = "shape mismatch"}+-- [[ newtype Array s a = Array {unArray :: V.Vector a} deriving (Eq, Ord, Functor, Foldable, Generic, Traversable) instance (HasShape s, Show a) => Show (Array s a) where@@ -199,32 +187,27 @@ negate = fmapRep negate instance- (HasShape s, Multiplicative a) =>- MultiplicativeAction (Array s a) a+ (Multiplicative a) =>+ MultiplicativeAction (Array s a) where- (.*) s r = fmap (s *) r- {-# INLINE (.*) #-}+ type Scalar (Array s a) = a+ (|*) r s = fmap (s *) r -instance- (HasShape s, Additive a) =>- AdditiveAction (Array s a) a- where- (.+) s r = fmap (s +) r- {-# INLINE (.+) #-}+instance (Additive a) => AdditiveAction (Array s a) where+ type AdditiveScalar (Array s a) = a+ (|+) r s = fmap (s +) r instance- (HasShape s, Subtractive a) =>- SubtractiveAction (Array s a) a+ (Subtractive a) =>+ SubtractiveAction (Array s a) where- (.-) s r = fmap (s -) r- {-# INLINE (.-) #-}+ (|-) r s = fmap (\x -> x - s) r instance- (HasShape s, Divisive a) =>- DivisiveAction (Array s a) a+ (Divisive a) =>+ DivisiveAction (Array s a) where- (./) s r = fmap (s /) r- {-# INLINE (./) #-}+ (|/) r s = fmap (/ s) r instance (HasShape s, JoinSemiLattice a) => JoinSemiLattice (Array s a) where (\/) = liftR2 (\/)@@ -232,7 +215,7 @@ instance (HasShape s, MeetSemiLattice a) => MeetSemiLattice (Array s a) where (/\) = liftR2 (/\) -instance (HasShape s, Subtractive a, Epsilon a, Ord a) => Epsilon (Array s a) where+instance (HasShape s, Subtractive a, Epsilon a) => Epsilon (Array s a) where epsilon = singleton epsilon instance@@ -277,6 +260,22 @@ r with (D.Array _ v) f = f (Array v) +-- | Takes the top-most elements according to the new dimension.+--+-- >>> takes a :: Array '[2,2,3] Int+-- [[[1, 2, 3],+-- [5, 6, 7]],+-- [[13, 14, 15],+-- [17, 18, 19]]]+takes ::+ forall s s' a.+ ( HasShape s,+ HasShape s'+ ) =>+ Array s a ->+ Array s' a+takes a = tabulate $ \s -> index a s+ -- | Reshape an array (with the same number of elements). -- -- >>> reshape a :: Array '[4,3,2] Int@@ -312,6 +311,15 @@ transpose :: forall a s. (HasShape s, HasShape (Reverse s)) => Array s a -> Array (Reverse s) a transpose a = tabulate (index a . reverse) +-- | Indices of an Array.+--+-- >>> indices :: Array '[3,3] [Int]+-- [[[0,0], [0,1], [0,2]],+-- [[1,0], [1,1], [1,2]],+-- [[2,0], [2,1], [2,2]]]+indices :: forall s. (HasShape s) => Array s [Int]+indices = tabulate id+ -- | The identity array. -- -- >>> ident :: Array '[3,2] Int@@ -326,16 +334,21 @@ isDiag [x, y] = x == y isDiag (x : y : xs) = x == y && isDiag (y : xs) --- | A sequential array of Ints+-- | An array of sequential Ints -- -- >>> sequent :: Array '[3] Int -- [0, 1, 2]+--+-- >>> sequent :: Array '[3,3] Int+-- [[0, 0, 0],+-- [0, 1, 0],+-- [0, 0, 2]] sequent :: forall s. (HasShape s) => Array s Int sequent = tabulate go where go [] = zero go [i] = i- go (i : j : _) = bool zero i (i == j)+ go (i : js) = bool zero i (all (i ==) js) -- | Extract the diagonal of an array. --@@ -354,6 +367,24 @@ go (s' : _) = index a (replicate (length ds) s') ds = shapeVal (toShape @s) +-- | Expand the array to form a diagonal array+--+-- >>> undiag ([1,1] :: Array '[2] Int)+-- [[1, 0],+-- [0, 1]]+undiag ::+ forall a s.+ ( HasShape s,+ Additive a,+ HasShape ((++) s s)+ ) =>+ Array s a ->+ Array ((++) s s) a+undiag a = tabulate go+ where+ go [] = throw (NumHaskException "Rank Underflow")+ go xs@(x : xs') = bool zero (index a xs) (all (x ==) xs')+ -- | Create an array composed of a single value. -- -- >>> singleton one :: Array '[3,2] Int@@ -436,7 +467,7 @@ -- -- >>> let e = extracts (Proxy :: Proxy '[1,2]) a -- >>> :t e--- e :: Array '[3, 4] (Array '[2] Int)+-- e :: Array [3, 4] (Array '[2] Int) extracts :: forall ds st si so a. ( HasShape st,@@ -457,7 +488,7 @@ -- -- >>> let e = extractsExcept (Proxy :: Proxy '[1,2]) a -- >>> :t e--- e :: Array '[2] (Array '[3, 4] Int)+-- e :: Array '[2] (Array [3, 4] Int) extractsExcept :: forall ds st si so a. ( HasShape st,@@ -479,12 +510,12 @@ -- >>> let e = extracts (Proxy :: Proxy '[1,0]) a -- -- >>> :t e--- e :: Array '[3, 2] (Array '[4] Int)+-- e :: Array [3, 2] (Array '[4] Int) -- -- >>> let j = joins (Proxy :: Proxy '[1,0]) e -- -- >>> :t j--- j :: Array '[2, 3, 4] Int+-- j :: Array [2, 3, 4] Int -- -- >>> a == j -- True@@ -507,7 +538,7 @@ -- | Maps a function along specified dimensions. -- -- >>> :t maps (transpose) (Proxy :: Proxy '[1]) a--- maps (transpose) (Proxy :: Proxy '[1]) a :: Array '[4, 3, 2] Int+-- maps (transpose) (Proxy :: Proxy '[1]) a :: Array [4, 3, 2] Int maps :: forall ds st st' si si' so a b. ( HasShape st,@@ -530,7 +561,7 @@ -- | Concatenate along a dimension. -- -- >>> :t concatenate (Proxy :: Proxy 1) a a--- concatenate (Proxy :: Proxy 1) a a :: Array '[2, 6, 4] Int+-- concatenate (Proxy :: Proxy 1) a a :: Array [2, 6, 4] Int concatenate :: forall a s0 s1 d s. ( CheckConcatenate d s0 s1 s,@@ -598,7 +629,7 @@ -- -- >>> :t append (Proxy :: Proxy 0) a -- append (Proxy :: Proxy 0) a--- :: Array '[3, 4] Int -> Array '[3, 3, 4] Int+-- :: Array [3, 4] Int -> Array [3, 3, 4] Int append :: forall a d s s'. ( DropIndex s d ~ s',@@ -619,7 +650,7 @@ -- -- >>> let r = reorder (Proxy :: Proxy '[2,0,1]) a -- >>> :t r--- r :: Array '[4, 2, 3] Int+-- r :: Array [4, 2, 3] Int reorder :: forall a ds s. ( HasShape ds,@@ -640,7 +671,7 @@ -- For context, if the function is multiply, and the arrays are tensors, -- then this can be interpreted as a tensor product. ----- https://en.wikipedia.org/wiki/Tensor_product+-- < https://en.wikipedia.org/wiki/Tensor_product> -- -- The concept of a tensor product is a dense crossroad, and a complete treatment is elsewhere. To quote: --@@ -650,6 +681,19 @@ -- [[1, 2, 3], -- [2, 4, 6], -- [3, 6, 9]]+--+-- Alternatively, expand can be understood as representing the permutation of element pairs of two arrays, so like the Applicative List instance.+--+-- >>> i2 = indices :: Array '[2,2] [Int]+-- >>> expand (,) i2 i2+-- [[[[([0,0],[0,0]), ([0,0],[0,1])],+-- [([0,0],[1,0]), ([0,0],[1,1])]],+-- [[([0,1],[0,0]), ([0,1],[0,1])],+-- [([0,1],[1,0]), ([0,1],[1,1])]]],+-- [[[([1,0],[0,0]), ([1,0],[0,1])],+-- [([1,0],[1,0]), ([1,0],[1,1])]],+-- [[([1,1],[0,0]), ([1,1],[0,1])],+-- [([1,1],[1,0]), ([1,1],[1,1])]]]] expand :: forall s s' a b c. ( HasShape s,@@ -664,7 +708,18 @@ where r = rank (shape a) -expand' ::+-- | Like expand, but permutes the first array first, rather than the second.+--+-- >>> expand (,) v (v |+ 3)+-- [[(1,4), (1,5), (1,6)],+-- [(2,4), (2,5), (2,6)],+-- [(3,4), (3,5), (3,6)]]+--+-- >>> expandr (,) v (v |+ 3)+-- [[(1,4), (2,4), (3,4)],+-- [(1,5), (2,5), (3,5)],+-- [(1,6), (2,6), (3,6)]]+expandr :: forall s s' a b c. ( HasShape s, HasShape s',@@ -674,13 +729,13 @@ Array s a -> Array s' b -> Array ((++) s s') c-expand' f a b = tabulate (\i -> f (index a (drop r i)) (index b (take r i)))+expandr f a b = tabulate (\i -> f (index a (drop r i)) (index b (take r i))) where r = rank (shape a) -- | Apply an array of functions to each array of values. ----- This is in the spirit of the applicative functor operation (<*>).+-- This is in the spirit of the applicative functor operation (\<*\>). -- -- > expand f a b == apply (fmap f a) b --@@ -689,14 +744,14 @@ -- [2, 4, 6], -- [3, 6, 9]] ----- Arrays can't be applicative functors in haskell because the changes in shape are reflected in the types.+-- Fixed Arrays can't be applicative functors because the changes in shape are reflected in the types. -- -- > :t apply--- apply--- :: (HasShape s, HasShape s', HasShape (s ++ s')) =>--- Array s (a -> b) -> Array s' a -> Array (s ++ s') b+-- > apply+-- > :: (HasShape s, HasShape s', HasShape (s ++ s')) =>+-- > Array s (a -> b) -> Array s' a -> Array (s ++ s') b -- > :t (<*>)--- (<*>) :: Applicative f => f (a -> b) -> f a -> f b+-- > (<*>) :: Applicative f => f (a -> b) -> f a -> f b -- -- >>> let b = [1..6] :: Array '[2,3] Int -- >>> contract sum (Proxy :: Proxy '[1,2]) (apply (fmap (*) b) (transpose b))@@ -767,24 +822,31 @@ -- >>> dot sum (*) b v -- [14, 32] ----- dot allows operation on mis-shaped matrices:------ >>> let m23 = [1..6] :: Array '[2,3] Int--- >>> let m12 = [1,2] :: Array '[1,2] Int--- >>> shape $ dot sum (*) m23 m12--- [2,2]+-- Array elements don't have to be numbers: ----- the algorithm ignores excess positions within the contracting dimension(s):+-- >>> x1 = (show <$> [1..4]) :: Array '[2,2] String+-- >>> x2 = (show <$> [5..8]) :: Array '[2,2] String+-- >>> x1+-- [["1", "2"],+-- ["3", "4"]] ----- m23 shape: 2 3+-- >>> x2+-- [["5", "6"],+-- ["7", "8"]] ----- m12 shape: 1 2+-- >>> import Data.List (intercalate)+-- >>> dot (intercalate "+" . toList) (\a b -> a <> "*" <> b) x1 x2+-- [["1*5+2*7", "1*6+2*8"],+-- ["3*5+4*7", "3*6+4*8"]] ----- res shape: 2 2+-- 'dot' allows operation on mis-shaped matrices. The algorithm ignores excess positions within the contracting dimension(s): ----- FIXME: work out whether this is a feature or a bug...+-- >>> let m23 = [1..6] :: Array '[2,3] Int+-- >>> let m12 = [1,2] :: Array '[1,2] Int+-- >>> shape $ dot sum (*) m23 m12+-- [2,2] ----- find instances of a vector in a matrix+-- Find instances of a vector in a matrix -- -- >>> let cs = fromList ("abacbaab" :: [Char]) :: Array '[4,2] Char -- >>> let v = fromList ("ab" :: [Char]) :: Vector 2 Char@@ -863,7 +925,7 @@ -- -- >>> let s = slice (Proxy :: Proxy '[[0,1],[0,2],[1,2]]) a -- >>> :t s--- s :: Array '[2, 2, 2] Int+-- s :: Array [2, 2, 2] Int -- -- >>> s -- [[[2, 3],@@ -893,15 +955,6 @@ go s = index a (zipWith (!!) pss' s) pss' = natValss pss -takes ::- forall s s' a.- ( HasShape s,- HasShape s'- ) =>- Array s a ->- Array s' a-takes a = tabulate $ \s -> index a s- -- | Remove single dimensions. -- -- >>> let a = [1..24] :: Array '[2,1,3,4,1] Int@@ -950,11 +1003,6 @@ -- $scalar -- Scalar specialisations --- | <https://en.wikipedia.org/wiki/Scalarr_(mathematics) Wiki Scalar>------ An Array '[] a despite being a Scalar is never-the-less a one-element vector under the hood. Unification of representation is unexplored.-type Scalar a = Array ('[] :: [Nat]) a- -- | Unwrapping scalars is probably a performance bottleneck. -- -- >>> let s = [3] :: Array ('[] :: [Nat]) Int@@ -973,6 +1021,7 @@ -- | <https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics) Wiki Vector> type Vector s a = Array '[s] a +-- | Vector specialisation of 'sequent' sequentv :: forall n. (KnownNat n) => Vector n Int sequentv = sequent @@ -1005,7 +1054,7 @@ where recip a = invtri (transpose (chol a)) * invtri (chol a) --- | inverse of a triangular matrix+-- | <https://math.stackexchange.com/questions/1003801/inverse-of-an-invertible-upper-triangular-matrix-of-order-3 Inverse of a triangular> matrix. invtri :: forall a n. (KnownNat n, ExpField a, Eq a) => Array '[n, n] a -> Array '[n, n] a invtri a = sum (fmap (l ^) (sequentv :: Vector n Int)) * ti where@@ -1013,25 +1062,9 @@ tl = a - undiag (diag a) l = negate (ti * tl) --- | Expand the array to form a diagonal array------ >>> undiag ([1,1] :: Array '[2] Int)--- [[1, 0],--- [0, 1]]-undiag ::- forall a s.- ( HasShape s,- Additive a,- HasShape ((++) s s)- ) =>- Array s a ->- Array ((++) s s) a-undiag a = tabulate go- where- go [] = throw (NumHaskException "Rank Underflow")- go xs@(x : xs') = bool zero (index a xs) (all (x ==) xs')- -- | cholesky decomposition+--+-- Uses the <https://en.wikipedia.org/wiki/Cholesky_decomposition#The_Cholesky_algorithm Cholesky-Crout> algorithm. chol :: (KnownNat n, ExpField a) => Array '[n, n] a -> Array '[n, n] a chol a = let l =
src/NumHask/Array/Shape.hs view
@@ -1,19 +1,7 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE RebindableSyntax #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StrictData #-}-{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeInType #-}-{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE NoStarIsType #-}-{-# OPTIONS_GHC -Wall #-} {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-} {-# OPTIONS_GHC -fno-warn-unused-top-binds #-} @@ -51,15 +39,19 @@ posRelative, PosRelative, PosRelativeGo,+ DecMap, addIndexes, AddIndexes, AddIndexesGo, dropIndexes, DropIndexes,+ DropIndexesGo, takeIndexes, TakeIndexes, exclude, Exclude,+ Enumerate,+ EnumerateGo, concatenate', Concatenate, CheckConcatenate,
− test/doctests.hs
@@ -1,8 +0,0 @@-module Main where--main :: IO ()-main = do- putStrLn "This test-suite exists only to add dependencies"- putStrLn "To run doctests: "- putStrLn " cabal build all --enable-tests"- putStrLn " cabal-docspec"