----------------------------------------------------------------------------- -- | -- Module : Data.Packed.Static.Vector -- Copyright : (c) Reiner Pope 2008 -- License : GPL-style -- -- Maintainer : Reiner Pope -- Stability : experimental -- Portability : portable -- -- Statically-dimensioned 1D vectors. -- ----------------------------------------------------------------------------- module Data.Packed.Static.Vector( Vector, -- * Shaping -- | Functions manipulating a vector's (static) shape. refineVec, atDim, atShape, -- * Construction by index buildVector, -- * To/from lists fromListU, toList, -- * Manipulation dim, (@>), subVectorU, joinU, constant, linspace, vectorMin, vectorMax, vectorMinIndex, vectorMaxIndex, liftVector, liftVector2, ) where import Data.Maybe(fromJust) import Data.List(intercalate) import qualified Numeric.LinearAlgebra as H import Data.Packed.Static.Shapes import Data.Packed.Static.Imports import Data.Packed.Static.Internal instance ShapedContainer Vector where type Unwrapped Vector = H.Vector unWrap = unVector wrapU = Vector type UnknownShape Vector = Unknown unsafeReshape = Vector . unVector ------ Shaping -- | \"Reifies\" a Vector's length in types. Useful when vectors of length "Unknown" -- need to be used for a statically-sized operations. For instance, if @v :: Vector Unknown Double@, -- then we can write -- -- @refineVec v (\v -> forgetSize $ v + constant 5)@ -- -- to add a constant vector of 5s with the appropriate size. refineVec :: forall m t a. Vector m t -> (forall n. PositiveT n => Vector n t -> a) -> a refineVec v k = fromJust $ reifyPositiveD (toInteger $ dim v) (\n -> k (unsafeReshape v `atShape` n)) withDim :: forall n a. PositiveT n => (Int -> Vector n a) -> Vector n a withDim f = f n where n = fromIntegerT (undefined :: n) {- | Sets an arbitrary-length vector to a specific value. @\> constant 1 `atDim` 5 [$vec| 1.0, 1.0, 1.0, 1.0, 1.0 |]@ -} atDim :: (forall n. PositiveT n => Vector n t) -> Int -> Vector Unknown t atDim v n | n > 0 = fromJust $ reifyPositiveD (toInteger n) (\n -> forgetShapeU $ v `atShape` n) | otherwise = error $ "atDim: negative vector length: " ++ show n ------- By-index construction {- | Builds a vector given a function from indices. Indexing is 0-based. @\> buildVector fromIntegral \`atShape\` d5 [$vec| 0.0, 1.0, 2.0, 3.0, 4.0 |]@ -} buildVector :: (PositiveT n, Element a) => (Int -> a) -> Vector n a buildVector f = withDim (\len -> Vector $ H.buildVector len f) -------- To / from lists {- | Constructs a vector from all the elements of a list. @\> fromListU [1,2,3,4,5] [$vec| 1.0, 2.0, 3.0, 4.0, 5.0 |]@ -} fromListU :: (Storable a) => [a] -> Vector Unknown a fromListU = Vector . H.fromList {- | Converts to a list of elements. @\> toList [$vec|1,2,3|] [1.0,2.0,3.0]@ -} toList :: (Storable a) => Vector n a -> [a] toList = H.toList . unVector ------ Other operations {- | Vector's length. @\> dim [$vec|1::Double,2,3|] 3@ -} dim :: Vector n t -> Int dim = H.dim . unVector {- | Indexes a vector. @\> [$vec|1,2,3|] \@\> 1 2.0@ -} (@>) :: (Storable t) => Vector n t -> Int -> t (@>) = (H.@>) . unVector {- | Extracts a subvector. @\> subVectorU 2 3 [$vec|1,2,3,4,5|] [$vec| 3.0, 4.0, 5.0 |]@ -} subVectorU :: (Storable t) => Int -- ^ Initial index -> Int -- ^ Length of resultant vector -> Vector n t -> Vector Unknown t subVectorU a b = Vector . H.subVector a b . unVector --- I say the input Size is unknown, although it can be anything, --- so users don't think all the vectors must be of the same size. {- | Joins each vector in the list. @\> joinU [[$vecU|1,2,3|], [$vecU|4,5|]] [$vec| 1.0, 2.0, 3.0, 4.0, 5.0 |]@ -} joinU :: (Storable t) => [Vector Unknown t] -> Vector Unknown t joinU = Vector . H.join . map unVector {- | Creates a constant vector of any length. The length is determined by the type. @\> [$vec|1,2,3|] + constant 2 [$vec| 3.0, 4.0, 5.0 |]@ -} constant :: (Element t, PositiveT n) => t -> Vector n t constant a = withDim (Vector . H.constant a) {- | Creates a vector of arbitrary length whose components range linearly from a to b. The vector's length is determined by its type. @\> linspace (1,5) `atShape` d4 [$vec| 1.0, 2.333333333333333, 3.6666666666666665, 5.0 |]@ -} linspace :: (PositiveT n) => (Double,Double) -> Vector n Double linspace r = withDim (\n -> Vector $ H.linspace n r) where {- | Gives the vector's minimum entry. @\> vectorMin [$vec|1,2,3|] 1.0@ -} vectorMin :: Vector n Double -> Double vectorMin = H.vectorMin . unVector {- | Gives the vector's maximum entry. @\> vectorMax [$vec|1,2,3|] 3.0@ -} vectorMax :: Vector n Double -> Double vectorMax = H.vectorMax . unVector {- | Gives the index of a vector's minimum entry. @\> vectorMinIndex [$vec|1,2,3|] 0@ -} vectorMinIndex :: Vector n Double -> Int vectorMinIndex = H.vectorMinIndex . unVector {- | Gives the index of a vector's maximum entry. @\> vectorMaxIndex [$vec|1,2,3|] 2@ -} vectorMaxIndex :: Vector n Double -> Int vectorMaxIndex = H.vectorMaxIndex . unVector {- | 'map' for vectors. @\> (*2) `liftVector` [$vec|1,2,3|] [$vec| 2.0, 4.0, 6.0 |]@ -} liftVector :: (Storable a, Storable b) => (a -> b) -> Vector n a -> Vector n b liftVector f = Vector . H.mapVector f . unVector --- note: this requires they are of the same size, whereas hmatrix allows --- different sizes; it uses the minimum size. {- | 'zipWith' for vectors. @\> liftVector2 (+) [$vec|1,2,3|] (constant 3) [$vec| 4.0, 5.0, 6.0 |]@ -} liftVector2 :: (Storable a, Storable b, Storable c) => (a -> b -> c) -> Vector n a -> Vector n b -> Vector n c liftVector2 f v1 v2 = Vector $ H.zipVector f (unVector v1) (unVector v2) instance (Storable e, Show e) => Show (Vector n e) where show v = "[$vec| " ++ intercalate ", " (map show $ toList v) ++ " |]"