hmatrix-static-0.3: Data/Packed/Static/Vector.hs
-----------------------------------------------------------------------------
-- |
-- Module : Data.Packed.Static.Vector
-- Copyright : (c) Reiner Pope 2008
-- License : GPL-style
--
-- Maintainer : Reiner Pope <reiner.pope@gmail.com>
-- 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) ++ " |]"