static-tensor-0.1.0.0: Tensors of statically known size

Copyright(C) 2017 Alexey Vagarenko
LicenseBSD-style (see LICENSE)
MaintainerAlexey Vagarenko (vagarenko@gmail.com)
Stabilityexperimental
Portabilitynon-portable
Safe HaskellNone
LanguageHaskell2010

Data.Tensor.Static

Contents

Description

 

Synopsis

Tensor class

class (PositiveDims dims ~ True, KnownNats dims) => IsTensor (dims :: [Nat]) e where Source #

Data family of unboxed tensors. Dimensions of a tensor are represented as type-level list of naturals. For instance, Tensor [3] Float is a vector of 3 Float elements; Tensor [4,3] Double is a matrix with 4 rows 3 columns of Double and so on.

Minimal complete definition

tensor, unsafeFromList, toList

Associated Types

data Tensor dims e :: Type Source #

Tensor data constructor for given size and element type.

Methods

tensor :: TensorConstructor dims e Source #

Alias for a concrete tensor data constructor.

>>> tensor @[2,2] @Int 0 1 2 3
Tensor'2'2 [[0,1],[2,3]]

unsafeFromList :: [e] -> Tensor dims e Source #

Build tensor from the list. The list must contain at least length elements or method will throw an exception.

toList :: Tensor dims e -> [] e Source #

Convert tensor to list.

Instances

IsTensor ([] Nat) e Source #

Scalar is a degenerate tensor.

Associated Types

data Tensor ([Nat] :: [Nat]) e :: Type Source #

type TensorConstructor (dims :: [Nat]) (e :: Type) = NAry (ElemsNumber dims) e (Tensor dims e) Source #

Type of a tensor data constructor.

>>> :kind! TensorConstructor '[2,2] Float
TensorConstructor '[2,2] Float :: *
= Float -> Float -> Float -> Float -> Tensor '[2, 2] Float

type family PositiveDims (dims :: [Nat]) :: Bool where ... Source #

Check if all dimensions are greater than 0.

Equations

PositiveDims '[] = True 
PositiveDims (d ': ds) = (1 <=? d) && PositiveDims ds 

Construction

fill :: forall (dims :: [Nat]) e. Fill dims e => e -> Tensor dims e Source #

Tensor filled with given elements.

zero :: (Fill dims e, Num e) => Tensor dims e Source #

Tensor filled with zeros.

enumFromN Source #

Arguments

:: forall (dims :: [Nat]). EnumFromN dims e 
=> e

Starting value.

-> Tensor dims e 

Tensor which elements are enumeration starting from given value.

type EnumFromN (dims :: [Nat]) e = (IsTensor dims e, EnumFromN (ElemsNumber dims), Num e) Source #

Constraints for enumFromN function.

enumFromStepN Source #

Arguments

:: forall (dims :: [Nat]). EnumFromStepN dims e 
=> e

Starting value.

-> e

Step.

-> Tensor dims e 

Tensor which elements are enumeration starting from given value with given step.

type EnumFromStepN (dims :: [Nat]) e = (IsTensor dims e, EnumFromStepN (ElemsNumber dims), Num e) Source #

Constraints for enumFromStepN function.

generate Source #

Arguments

:: forall (dims :: [Nat]) (e :: Type) (kctx :: Type) (ctx :: kctx). Generate dims e kctx ctx 
=> (forall (index :: [Nat]). MkCtx [Nat] kctx ctx index => Proxy index -> e)

Generator function that takes index as type parameter will be called for each index.

-> Tensor dims e 

Generate a tensor by applying the function to each index. ctx type parameter is a producer of constraint of kind kctx for each index. See MkCtx for more info.

>>> import Data.Singletons
>>> type Ctx (dims :: [Nat]) (index :: [Nat]) = KnownNat (FlattenIndex index dims); $(genDefunSymbols [''Ctx])
>>> generate @[2,3,4] @Int @([Nat] ~> Constraint) @(CtxSym1 [2,3,4]) $ \(Proxy :: Proxy index) -> fromIntegral $ natVal (Proxy @(FlattenIndex index [2,3,4]))
Tensor'2'3'4 [[[0,1,2,3],[4,5,6,7],[8,9,10,11]],[[12,13,14,15],[16,17,18,19],[20,21,22,23]]]

type Generate (dims :: [Nat]) (e :: Type) (kctx :: Type) (ctx :: kctx) = (IsTensor dims e, DemoteWith [Nat] kctx ctx (AllIndexes dims)) Source #

Constraints for generate function.

Tensor shape

dimensions :: forall (dims :: [Nat]). KnownNats dims => [Int] Source #

Dimensions of a tensor.

elemsNumber :: forall (dims :: [Nat]). KnownNat (ElemsNumber dims) => Int Source #

Number of elements in a tensor.

subtensorsElemsNumbers :: forall (dims :: [Nat]). KnownNats (SubtensorsElemsNumbers dims) => [Int] Source #

Number of elements of all subtensors of a tensor.

>>> subtensorsElemsNumbers @[2,3,4]
[12,4,1]
>>> subtensorsElemsNumbers @[4,4]
[4,1]

type family ElemsNumber (dims :: [Nat]) :: Nat where ... Source #

Number of elements in a tensor.

Equations

ElemsNumber '[] = 1 
ElemsNumber (d ': ds) = d * ElemsNumber ds 

type SubtensorsElemsNumbers (dims :: [Nat]) = Tail (SubtensorsElemsNumbers' dims) Source #

Number of elements of all subtensors of a tensor with given shape dims.

>>> :kind! SubtensorsElemsNumbers '[2,3,4]
SubtensorsElemsNumbers '[2,3,4] :: [Nat]
= '[12, 4, 1]
>>> :kind! SubtensorsElemsNumbers '[4,4]
SubtensorsElemsNumbers '[4,4] :: [Nat]
= '[4, 1]

type FlattenIndex (index :: [Nat]) (dims :: [Nat]) = FlattenIndex' index (SubtensorsElemsNumbers dims) Source #

Convert multidimentional index in tensor of shape dims to flat index. index parameter must have the same length as dims.

>>> :kind! FlattenIndex '[1,1,1] '[2,3,4]
FlattenIndex '[1,1,1] '[2,3,4] :: Nat
= 17

type AllIndexes (dims :: [Nat]) = Sequence (IndexesRanges dims) Source #

Sequence of all indexes in a tensor of shape dims.

>>> :kind! AllIndexes '[2,3,4]
AllIndexes '[2,3,4] :: [[Nat]]
= '['[0, 0, 0], '[0, 0, 1], '[0, 0, 2], '[0, 0, 3], '[0, 1, 0],
    '[0, 1, 1], '[0, 1, 2], '[0, 1, 3], '[0, 2, 0], '[0, 2, 1],
    '[0, 2, 2], '[0, 2, 3], '[1, 0, 0], '[1, 0, 1], '[1, 0, 2],
    '[1, 0, 3], '[1, 1, 0], '[1, 1, 1], '[1, 1, 2], '[1, 1, 3],
    '[1, 2, 0], '[1, 2, 1], '[1, 2, 2], '[1, 2, 3]]

type NatsFromTo (from :: Nat) (to :: Nat) = NatsFromTo' from to (from <=? to) Source #

Generate range of naturals starting from from param inclusive and up to to param inclusive.

type family NormalizeDims (dims :: [Nat]) :: [Nat] where ... Source #

Remove unit dimentions, i.e. dimensions with size 1.

>>> :kind! NormalizeDims '[2, 1, 3]
'[2, 3]

Equations

NormalizeDims '[] = '[] 
NormalizeDims (1 ': xs) = NormalizeDims xs 
NormalizeDims (x ': xs) = x ': NormalizeDims xs 

Modifying tensors

withTensor Source #

Arguments

:: (IsTensor dims e, ApplyNAry (ElemsNumber dims) e r) 
=> Tensor dims e

The tensor.

-> NAry (ElemsNumber dims) e r

Function with number of params equal to number of tensor elements.

-> r 

Pass tensor elements to a function.

>>> withTensor (matrix @2 @2 @Float 0 1 2 3) (\a b c d -> a * d - b * c)
-2.0
>>> withTensor (vector @2 @Float 3 4) (\x y -> sqrt $ x * x + y * y)
5.0

add :: Add dims e => Tensor dims e -> Tensor dims e -> Tensor dims e Source #

Add two tensors element-wise.

type Add (dims :: [Nat]) e = (IsTensor dims e, Num e, ZipWith (ElemsNumber dims), Zip (ElemsNumber dims), Unzip (ElemsNumber dims), Map (ElemsNumber dims)) Source #

Constraints for add.

diff :: Diff dims e => Tensor dims e -> Tensor dims e -> Tensor dims e Source #

Substract two tensors element-wise.

type Diff (dims :: [Nat]) e = (IsTensor dims e, Num e, ZipWith (ElemsNumber dims), Zip (ElemsNumber dims), Unzip (ElemsNumber dims), Map (ElemsNumber dims)) Source #

Constraints for diff.

scale :: Scale dims e => Tensor dims e -> e -> Tensor dims e Source #

Multiply every element of a tensor by given value.

type Scale (dims :: [Nat]) e = (IsTensor dims e, Num e, Map (ElemsNumber dims)) Source #

Constraints for scale.

Concatenation

cons Source #

Arguments

:: forall (axis :: Nat) (dims :: [Nat]). Cons axis dims e 
=> Tensor (NormalizeDims (ConsSubtensorDims axis dims)) e

Subtensor to cons.

-> Tensor dims e

Tensor to cons to.

-> Tensor (DimsAfterCons axis dims) e 

Prepend a subtensor along axis to the tensor with shape dims

>>> cons @0 (enumFromStepN @[3,4] @Int (-1) (-1)) (enumFromN @[2,3,4] 0)
Tensor'3'3'4 [[[ -1,  -2,  -3,  -4]
              ,[ -5,  -6,  -7,  -8]
              ,[ -9, -10, -11, -12]]
             ,[[  0,   1,   2,   3]
              ,[  4,   5,   6,   7]
              ,[  8,   9,  10,  11]]
             ,[[ 12,  13,  14,  15]
              ,[ 16,  17,  18,  19]
              ,[ 20,  21,  22,  23]]]
>>> cons @1 (enumFromStepN @[2,4] @Int (-1) (-1)) (enumFromN @[2,3,4] 0)
Tensor'2'4'4 [[[ -1,  -2,  -3,  -4]
              ,[  0,   1,   2,   3]
              ,[  4,   5,   6,   7]
              ,[  8,   9,  10,  11]]
             ,[[ -5,  -6,  -7,  -8]
              ,[ 12,  13,  14,  15]
              ,[ 16,  17,  18,  19]
              ,[ 20,  21,  22,  23]]]
>>> cons @2 (enumFromStepN @[2,3] @Int (-1) (-1)) (enumFromN @[2,3,4] 0)
Tensor'2'3'5 [[[ -1,   0,   1,   2,   3]
              ,[ -2,   4,   5,   6,   7]
              ,[ -3,   8,   9,  10,  11]]
             ,[[ -4,  12,  13,  14,  15]
              ,[ -5,  16,  17,  18,  19]
              ,[ -6,  20,  21,  22,  23]]]

type Cons (axis :: Nat) (dims :: [Nat]) e = (SetSlice (ConsSubtensorStartingIndex dims) (ConsSubtensorDims axis dims) (DimsAfterCons axis dims) e, SetSlice (ConsTensorStartingIndex axis dims) dims (DimsAfterCons axis dims) e, dims ~ NormalizeDims dims, Fill (DimsAfterCons axis dims) e) Source #

Constraints for cons.

type ConsSubtensorDims (axis :: Nat) (dims :: [Nat]) = ConsSubtensorDims' axis dims 0 Source #

Shape of subtensor being cons'ed to the tensor dims.

>>> :kind! ConsSubtensorDims 0 [2,3,4]
ConsSubtensorDims 0 [2,3,4] :: [Nat] 
= '[1, 3, 4]                
>>> :kind! ConsSubtensorDims 1 [2,3,4]
ConsSubtensorDims 1 [2,3,4] :: [Nat] 
= '[2, 1, 4]                
>>> :kind! ConsSubtensorDims 2 [2,3,4]
ConsSubtensorDims 2 [2,3,4] :: [Nat] 
= '[2, 3, 1]                

type family DimsAfterCons (axis :: Nat) (dims :: [Nat]) :: [Nat] where ... Source #

Shape of the tensor after cons'ing

>>> :kind! DimsAfterCons 0 [2,3,4]
DimsAfterCons 0 [2,3,4] :: [Nat]
= '[3, 3, 4]
>>> :kind! DimsAfterCons 1 [2,3,4]
DimsAfterCons 1 [2,3,4] :: [Nat]
= '[2, 4, 4]
>>> :kind! DimsAfterCons 2 [2,3,4]
DimsAfterCons 2 [2,3,4] :: [Nat]
= '[2, 3, 5]

Equations

DimsAfterCons 0 (d ': ds) = (d + 1) ': ds 
DimsAfterCons a (d ': ds) = d ': DimsAfterCons (a - 1) ds 
DimsAfterCons _ '[] = TypeError (Text "DimsAfterCons: axis must be in range [0..(number of dimensions in the tensor)].") 

snoc Source #

Arguments

:: forall (axis :: Nat) (dims :: [Nat]). Snoc axis dims e 
=> Tensor dims e

Tensor to snoc to.

-> Tensor (NormalizeDims (SnocSubtensorDims axis dims)) e

Subtensor to snoc.

-> Tensor (DimsAfterSnoc axis dims) e 

Append a subtensor along axis to the tensor with shape dims

>>> snoc @0 (enumFromN @[2,3,4] 0) (enumFromStepN @[3,4] @Int (-1) (-1))
Tensor'3'3'4 [[[  0,   1,   2,   3]
              ,[  4,   5,   6,   7]
              ,[  8,   9,  10,  11]]
             ,[[ 12,  13,  14,  15]
              ,[ 16,  17,  18,  19]
              ,[ 20,  21,  22,  23]]
             ,[[ -1,  -2,  -3,  -4]
              ,[ -5,  -6,  -7,  -8]
              ,[ -9, -10, -11, -12]]]
>>> snoc @1 (enumFromN @[2,3,4] 0) (enumFromStepN @[2,4] @Int (-1) (-1))
Tensor'2'4'4 [[[  0,   1,   2,   3]
              ,[  4,   5,   6,   7]
              ,[  8,   9,  10,  11]
              ,[ -1,  -2,  -3,  -4]]
             ,[[ 12,  13,  14,  15]
              ,[ 16,  17,  18,  19]
              ,[ 20,  21,  22,  23]
              ,[ -5,  -6,  -7,  -8]]]
>>> snoc @2 (enumFromN @[2,3,4] 0) (enumFromStepN @[2,3] @Int (-1) (-1))
Tensor'2'3'5 [[[  0,   1,   2,   3,  -1]
              ,[  4,   5,   6,   7,  -2]
              ,[  8,   9,  10,  11,  -3]]
             ,[[ 12,  13,  14,  15,  -4]
              ,[ 16,  17,  18,  19,  -5]
              ,[ 20,  21,  22,  23,  -6]]]

type Snoc (axis :: Nat) (dims :: [Nat]) e = (SetSlice (SnocSubtensorStartingIndex axis dims) (SnocSubtensorDims axis dims) (DimsAfterSnoc axis dims) e, SetSlice (SnocTensorStartingIndex dims) dims (DimsAfterSnoc axis dims) e, dims ~ NormalizeDims dims, Fill (DimsAfterSnoc axis dims) e) Source #

Constraints for snoc.

type SnocSubtensorDims (axis :: Nat) (dims :: [Nat]) = SnocSubtensorDims' axis dims 0 Source #

Shape of subtensor being snoc'ed to the tensor dims.

>>> :kind! SnocSubtensorDims 0 [2,3,4]
SnocSubtensorDims 0 [2,3,4] :: [Nat] 
= '[1, 3, 4]
>>> :kind! SnocSubtensorDims 1 [2,3,4]
SnocSubtensorDims 1 [2,3,4] :: [Nat] 
= '[2, 1, 4]
>>> :kind! SnocSubtensorDims 2 [2,3,4]
SnocSubtensorDims 2 [2,3,4] :: [Nat] 
= '[2, 3, 1]

type family DimsAfterSnoc (axis :: Nat) (dims :: [Nat]) :: [Nat] where ... Source #

Shape of the tensor after snoc'ing

>>> :kind! DimsAfterSnoc 0 [2,3,4]
DimsAfterSnoc 0 [2,3,4] :: [Nat]
= '[3, 3, 4]
>>> :kind! DimsAfterSnoc 1 [2,3,4]
DimsAfterSnoc 1 [2,3,4] :: [Nat]
= '[2, 4, 4]
>>> :kind! DimsAfterSnoc 2 [2,3,4]
DimsAfterSnoc 2 [2,3,4] :: [Nat]
= '[2, 3, 5]

Equations

DimsAfterSnoc 0 (d ': ds) = (d + 1) ': ds 
DimsAfterSnoc a (d ': ds) = d ': DimsAfterSnoc (a - 1) ds 
DimsAfterSnoc _ '[] = TypeError (Text "DimsAfterSnoc: axis must be in range [0..(number of dimensions in the tensor)].") 

append Source #

Arguments

:: forall (axis :: Nat) (dims0 :: [Nat]) (dims1 :: [Nat]). Append axis dims0 dims1 e 
=> Tensor dims0 e 
-> Tensor dims1 e 
-> Tensor (DimsAfterAppend axis dims0 dims1) e 

Append the second tensor dims1 to the first tensor dims0 along axis.

>>> append @0 (enumFromN @[2,3,4] 0) (enumFromStepN @[2,3,4] @Int (-1) (-1))
Tensor'4'3'4 [[[   0,   1,   2,   3]
              ,[   4,   5,   6,   7]
              ,[   8,   9,  10,  11]]
             ,[[  12,  13,  14,  15]
              ,[  16,  17,  18,  19]
              ,[  20,  21,  22,  23]]
             ,[[  -1,  -2,  -3,  -4]
              ,[  -5,  -6,  -7,  -8]
              ,[  -9, -10, -11, -12]]
             ,[[ -13, -14, -15, -16]
              ,[ -17, -18, -19, -20]
              ,[ -21, -22, -23, -24]]]
>>> append @1 (enumFromN @[2,3,4] 0) (enumFromStepN @[2,3,4] @Int (-1) (-1))
Tensor'2'6'4 [[[   0,   1,   2,   3]
              ,[   4,   5,   6,   7]
              ,[   8,   9,  10,  11]
              ,[  -1,  -2,  -3,  -4]
              ,[  -5,  -6,  -7,  -8]
              ,[  -9, -10, -11, -12]]
             ,[[  12,  13,  14,  15]
              ,[  16,  17,  18,  19]
              ,[  20,  21,  22,  23]
              ,[ -13, -14, -15, -16]
              ,[ -17, -18, -19, -20]
              ,[ -21, -22, -23, -24]]]
>>> append @2 (enumFromN @[2,3,4] 0) (enumFromStepN @[2,3,4] @Int (-1) (-1))
Tensor'2'3'8 [[[   0,   1,   2,   3,  -1,  -2,  -3,  -4]
              ,[   4,   5,   6,   7,  -5,  -6,  -7,  -8]
              ,[   8,   9,  10,  11,  -9, -10, -11, -12]]
             ,[[  12,  13,  14,  15, -13, -14, -15, -16]
              ,[  16,  17,  18,  19, -17, -18, -19, -20]
              ,[  20,  21,  22,  23, -21, -22, -23, -24]]]

type Append (axis :: Nat) (dims0 :: [Nat]) (dims1 :: [Nat]) e = (SetSlice (AppendFstTensorStartingIndex dims0) dims0 (DimsAfterAppend axis dims0 dims1) e, SetSlice (AppendSndTensorStartingIndex axis dims1) dims1 (DimsAfterAppend axis dims0 dims1) e, dims0 ~ NormalizeDims dims0, dims1 ~ NormalizeDims dims1, Fill (DimsAfterAppend axis dims0 dims1) e) Source #

Constraints for append.

type DimsAfterAppend (axis :: Nat) (dims0 :: [Nat]) (dims1 :: [Nat]) = DimsAfterAppend' axis dims0 dims1 0 Source #

Shape of the tensor after appending

>>> :kind! DimsAfterAppend 0 [2,3,4] [5,3,4]
DimsAfterAppend 0 [2,3,4] [5,3,4] :: [Nat]
= '[7, 3, 4]
>>> :kind! DimsAfterAppend 1 [2,3,4] [2,5,4]
DimsAfterAppend 1 [2,3,4] [2,5,4] :: [Nat]
= '[2, 8, 4]
>>> :kind! DimsAfterAppend 2 [2,3,4] [2,3,5]
DimsAfterAppend 2 [2,3,4] [2,3,5] :: [Nat]
= '[2, 3, 9]

Removing slices

remove Source #

Arguments

:: forall (axis :: Nat) (indexOnAxis :: Nat) (dims :: [Nat]). Remove axis indexOnAxis dims e 
=> Tensor dims e 
-> Tensor (DimsAfterRemove axis indexOnAxis dims) e 

Remove a slice from the tensor. We can only remove slices which have one dimension fewer than the tensor, and which span from borders of the tensor to opposite borders of the tensor (i.e. contain all elements of the tensor in their dimensions).

axis is the index of dimension in dims indexOnAxis is offset along axis that points to the slice to be removed.

For example, suppose we have tensor t :: Tensor '[2,3,4] Float that is, tensor made of two matrices of 3*4 elements.

If we want to remove first matrix we write remove @0 @0 t, if second - remove @0 @1 t.

If we want to remove n-th row in all matrices we write remove @1 @n t.

If we want to remove n-th column in all matrices we write remove @2 @n t.

>>> let t = enumFromN @[2,3,4] @Int 0
>>> t
Tensor'2'3'4 [[[ 0, 1, 2, 3]
              ,[ 4, 5, 6, 7]
              ,[ 8, 9,10,11]]
             ,[[12,13,14,15]
              ,[16,17,18,19]
              ,[20,21,22,23]]]
>>> remove @0 @0 t
Tensor'1'3'4 [[[12,13,14,15]
              ,[16,17,18,19]
              ,[20,21,22,23]]]
>>> remove @1 @0 t
Tensor'2'2'4 [[[ 4, 5, 6, 7]
              ,[ 8, 9,10,11]]
             ,[[16,17,18,19]
              ,[20,21,22,23]]]
>>> remove @2 @0 t
Tensor'2'3'3 [[[ 1, 2, 3]
              ,[ 5, 6, 7]
              ,[ 9,10,11]]
             ,[[13,14,15]
              ,[17,18,19]
              ,[21,22,23]]]

type Remove (axis :: Nat) (indexOnAxis :: Nat) (dims :: [Nat]) e = (IsTensor dims e, IsTensor (DimsAfterRemove axis indexOnAxis dims) e, RemoveWrk (ElemsInSlice (RemoveSliceStartIndex axis indexOnAxis dims) (RemoveSliceDims axis indexOnAxis dims) dims)) Source #

Constraints for remove.

type family DimsAfterRemove (axis :: Nat) (index :: Nat) (dims :: [Nat]) :: [Nat] where ... Source #

Shape of a tensor dims after removing a slice at index along axis.

>>> :kind! DimsAfterRemove 0 0 [2,3,4]
DimsAfterRemove 0 0 [2,3,4] :: [Nat]
= '[1, 3, 4]
>>> :kind! DimsAfterRemove 1 0 [2,3,4]
DimsAfterRemove 1 0 [2,3,4] :: [Nat]
= '[2, 2, 4]
>>> :kind! DimsAfterRemove 2 0 [2,3,4]
DimsAfterRemove 2 0 [2,3,4] :: [Nat]
= '[2, 3, 3]

Equations

DimsAfterRemove _ _ '[] = TypeError (Text "DimsAfterRemove: axis must be in range [0..(number of dimensions in the tensor)].") 
DimsAfterRemove 0 i (d ': ds) = If (i <=? (d - 1)) ((d - 1) ': ds) (TypeError ((((Text "DimsAfterRemove: Index " :<>: ShowType i) :<>: Text " is outside of the range of dimension [0..") :<>: ShowType (d - 1)) :<>: Text "].")) 
DimsAfterRemove a i (d ': ds) = d ': DimsAfterRemove (a - 1) i ds 

Conversion

type family NestedList (depth :: Nat) (e :: Type) :: Type where ... Source #

Nested list of given depth.

>>> :kind! NestedList 3 Float
[[[Float]]]
>>> :kind! NestedList 2 Float
[[Float]]

Equations

NestedList 0 e = e 
NestedList n e = [NestedList (n - 1) e] 

toNestedList Source #

Arguments

:: ToNestedList dims e 
=> Tensor dims e 
-> NestedList (Length dims) e 

Convert tensor to nested list.

type ToNestedList (dims :: [Nat]) e = (IsTensor dims e, ToNestedListWrk dims e) Source #

Constraints for toNestedList function.

Tensor elements

tensorElem Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). TensorElem index dims e 
=> Lens' (Tensor dims e) e 

Lens for an element of a tensor.

>>> let t = enumFromN @[2,3,4] @Int 0
>>> t
Tensor'2'3'4 [[[  0,  1,  2,  3]
              ,[  4,  5,  6,  7]
              ,[  8,  9, 10, 11]]
             ,[[ 12, 13, 14, 15]
              ,[ 16, 17, 18, 19]
              ,[ 20, 21, 22, 23]]]
>>> t ^. tensorElem @[1,1,1]
17
>>> set (tensorElem @[1,1,1]) 0 t
Tensor'2'3'4 [[[  0,  1,  2,  3]
              ,[  4,  5,  6,  7]
              ,[  8,  9, 10, 11]]
             ,[[ 12, 13, 14, 15]
              ,[ 16,  0, 18, 19]
              ,[ 20, 21, 22, 23]]]

type TensorElem index dims e = (SubtensorCtx index dims e, NormalizeDims (SubtensorDims index dims) ~ '[]) Source #

Constraint for tensorElem function.

Subtensors

type Subtensor index dims e = Tensor (NormalizeDims (SubtensorDims index dims)) e Source #

Subtensor at index of a tensor of shape dims.

>>> :kind! Subtensor '[] '[2,3,4] Float
Subtensor '[] '[2,3,4] Float :: *
= Tensor '[2, 3, 4] Float
>>> :kind! Subtensor '[0] '[2,3,4] Float
Subtensor '[0] '[2,3,4] Float :: *
= Tensor '[3, 4] Float
>>> :kind! Subtensor '[0,0] '[2,3,4] Float
Subtensor '[0,0] '[2,3,4] Float :: *
= Tensor '[4] Float
>>> :kind! Subtensor '[0,0,0] '[2,3,4] Float
Subtensor '[0,0,0] '[2,3,4] Float :: *
= Tensor '[] Float

type family SubtensorStartIndex (index :: [Nat]) (dims :: [Nat]) :: [Nat] where ... Source #

Index of the first element of the subtensor of the tensor of shape dims at index. This function returns index with number of dimensions equal to number of dimensions of the tensor.

>>> :kind! SubtensorStartIndex '[1] '[2,3,4]
SubtensorStartIndex '[1] '[2,3,4] :: [Nat]
= '[1, 0, 0]
>>> :kind! SubtensorStartIndex '[0,1] '[2,3,4]
SubtensorStartIndex '[0,1] '[2,3,4] :: [Nat]
= '[0, 1, 0]
>>> :kind! SubtensorStartIndex '[1,1] '[2,3,4]
SubtensorStartIndex '[1,1] '[2,3,4] :: [Nat]
= '[1, 1, 0]

Equations

SubtensorStartIndex '[] '[] = '[] 
SubtensorStartIndex (i ': is) '[] = TypeError (Text "SubtensorStartIndex: Too many dimensions in the index for subtensor.") 
SubtensorStartIndex '[] (d ': ds) = 0 ': SubtensorStartIndex '[] ds 
SubtensorStartIndex (i ': is) (d ': ds) = If (i <=? (d - 1)) (i ': SubtensorStartIndex is ds) (TypeError ((((Text "SubtensorStartIndex: Index " :<>: ShowType i) :<>: Text " is outside of the range of dimension [0..") :<>: ShowType (d - 1)) :<>: Text "].")) 

type family SubtensorDims (index :: [Nat]) (dims :: [Nat]) :: [Nat] where ... Source #

Shape of a subtensor of tensor of shape dims located at index. Resulting shape is not normalized.

>>> :kind! SubtensorDims '[0] '[2,3,4]
SubtensorDims '[0] '[2,3,4] :: [Nat]
= '[1, 3, 4]
>>> :kind! SubtensorDims '[0,0] '[2,3,4]
SubtensorDims '[0,0] '[2,3,4] :: [Nat]
= '[1, 1, 4]

Equations

SubtensorDims '[] ds = ds 
SubtensorDims (_ ': _) '[] = TypeError (Text "SubtensorDims: Too many dimensions in the index for subtensor.") 
SubtensorDims (i ': is) (d ': ds) = If (i <=? (d - 1)) (1 ': SubtensorDims is ds) (TypeError ((((Text "SubtensorDims: Index " :<>: ShowType i) :<>: Text " is outside of the range of dimension [0..") :<>: ShowType (d - 1)) :<>: Text "].")) 

subtensor Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). SubtensorCtx index dims e 
=> Lens' (Tensor dims e) (Subtensor index dims e) 

Lens for subtensor at given index.

>>> let t = enumFromN @[2,3,4] @Int 0
>>> t
Tensor'2'3'4 [[[  0,  1,  2,  3]
              ,[  4,  5,  6,  7]
              ,[  8,  9, 10, 11]]
             ,[[ 12, 13, 14, 15]
              ,[ 16, 17, 18, 19]
              ,[ 20, 21, 22, 23]]]
>>> t ^. subtensor @'[0]
Tensor'3'4    [[  0,  1,  2,  3]
              ,[  4,  5,  6,  7]
              ,[  8,  9, 10, 11]]
>>> t ^. subtensor @'[1]
Tensor'3'4    [[ 12, 13, 14, 15]
              ,[ 16, 17, 18, 19]
              ,[ 20, 21, 22, 23]]
>>> t ^. subtensor @'[0,0]
Tensor'4       [  0,  1,  2,  3]
>>> t ^. subtensor @'[1,0]
Tensor'4       [ 12, 13, 14, 15]

type SubtensorCtx index dims e = (GetSubtensor index dims e, SetSubtensor index dims e) Source #

Constraint for subtensor function.

getSubtensor Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). GetSubtensor index dims e 
=> Tensor dims e 
-> Subtensor index dims e 

Extract subtensor at given index.

type GetSubtensor index dims e = GetSlice (SubtensorStartIndex index dims) (SubtensorDims index dims) dims e Source #

Constraint for getSubtensor function.

getSubtensorElems Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). GetSubtensorElems index dims e 
=> Tensor dims e 
-> [e] 

Extract elements of subtensor at given index. Like getSubtensor, but without building actual subtensor.

type GetSubtensorElems index dims e = GetSliceElems (SubtensorStartIndex index dims) (SubtensorDims index dims) dims e Source #

Constraint for getSubtensorElems function.

setSubtensor Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). SetSubtensor index dims e 
=> Tensor dims e

The tensor.

-> Subtensor index dims e

New subtensor.

-> Tensor dims e 

Set subtensor at given index.

type SetSubtensor index dims e = SetSlice (SubtensorStartIndex index dims) (SubtensorDims index dims) dims e Source #

Constraint for setSubtensor function.

setSubtensorElems Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). SetSubtensorElems index dims e 
=> Tensor dims e

The tensor.

-> [e]

New elements of the subtensor.

-> Maybe (Tensor dims e) 

Like setSubtensor but takes a list of elements instead of a tensor. Returns Nothing if list has not enough elements.

type SetSubtensorElems index dims e = SetSliceElems (SubtensorStartIndex index dims) (SubtensorDims index dims) dims e Source #

Constraint for setSubtensorElems function.

mapSubtensorElems Source #

Arguments

:: forall (index :: [Nat]) (dims :: [Nat]). MapSubtensorElems index dims e 
=> Tensor dims e

The tensor.

-> (e -> e)

The mapping function.

-> Tensor dims e 

Modify subtensor elements with a function.

type MapSubtensorElems index dims e = MapSliceElems (SubtensorStartIndex index dims) (SubtensorDims index dims) dims e Source #

Constraints for mapSubtensorElems.

Slices

type family SliceEndIndex (startIndex :: [Nat]) (sliceDims :: [Nat]) (dims :: [Nat]) :: [Nat] where ... Source #

Index of the end of the slice of the tensor. startIndex parameter is the starting index of the slice, sliceDims is the shape of the slice, dims is the shape of the tensor. The slice must be contained inside the tensor. All dimensions of the slice must be positive. startIndex, sliceDims and dims must have the same length. If you want to get slice of lower rank than the tensor's, set one or more dimensions in sliceDims to 1.

>>> :kind! SliceEndIndex '[0,0,0] '[2,2,2] '[2,3,4]
SliceEndIndex '[0,0,0] '[2,2,2] '[2,3,4] :: [Nat]
= '[1, 1, 1]
>>> :kind! SliceEndIndex '[1,1,0] '[1,2,4] '[2,3,4]
SliceEndIndex '[1,1,0] '[1,2,4] '[2,3,4] :: [Nat]
= '[1, 2, 3]

Equations

SliceEndIndex '[] '[] '[] = '[] 
SliceEndIndex '[] '[] (d ': ds) = TypeError (Text "SliceEndIndex: Slice and its starting index have not enough dimensions.") 
SliceEndIndex '[] (sd ': sds) '[] = TypeError (Text "SliceEndIndex: Slice has too many dimensions.") 
SliceEndIndex '[] (sd ': sds) (d ': ds) = TypeError (Text "SliceEndIndex: Starting index of the slice has not enough dimensions.") 
SliceEndIndex (si ': sis) '[] '[] = TypeError (Text "SliceEndIndex: Starting index of the slice has too many dimensions.") 
SliceEndIndex (si ': sis) '[] (d ': ds) = TypeError (Text "SliceEndIndex: Slice has not enough dimensions.") 
SliceEndIndex (si ': sis) (sd ': sds) '[] = TypeError (Text "SliceEndIndex: Slice and its starting index have too many dimensions.") 
SliceEndIndex (si ': sis) (sd ': sds) (d ': ds) = SliceEndIndex' (si ': sis) (sd ': sds) (d ': ds) (1 <=? sd) 

type ElemsInSlice (startIndex :: [Nat]) (sliceDims :: [Nat]) (dims :: [Nat]) = ElemsInSlice' startIndex (SliceEndIndex startIndex sliceDims dims) (AllIndexes dims) Source #

Check each element of the tensor of shape dims if it is inside the slice from startIndex of shape sliceDims. The slice must be contained inside the tensor. All dimensions of the slice must be positive. startIndex, sliceDims and dims must have the same length.

>>> :kind! ElemsInSlice '[0,0,0] '[2,2,2] '[2,3,4]
ElemsInSlice '[0,0,0] '[2,2,2] '[2,3,4] :: [Bool]
= '['True, 'True, 'False, 'False, 'True, 'True, 'False, 'False,
    'False, 'False, 'False, 'False, 'True, 'True, 'False, 'False,
    'True, 'True, 'False, 'False, 'False, 'False, 'False, 'False]
>>> :kind! ElemsInSlice '[1,1,0] '[1,2,4] '[2,3,4]
ElemsInSlice '[1,1,0] '[1,2,4] '[2,3,4] :: [Bool]
= '['False, 'False, 'False, 'False, 'False, 'False, 'False, 'False,
    'False, 'False, 'False, 'False, 'False, 'False, 'False, 'False,
    'True, 'True, 'True, 'True, 'True, 'True, 'True, 'True]

slice Source #

Arguments

:: Slice startIndex sliceDims dims e 
=> Lens' (Tensor dims e) (Tensor (NormalizeDims sliceDims) e) 

Lens for the slice starting from startIndex of shape sliceDims of the tensor of shape dims.

>>> let t = (enumFromN @[2,3,4] @Int 0)
>>> t
Tensor'2'3'4 [[[  0,  1,  2,  3]
              ,[  4,  5,  6,  7]
              ,[  8,  9, 10, 11]]
             ,[[ 12, 13, 14, 15]
              ,[ 16, 17, 18, 19]
              ,[ 20, 21, 22, 23]]]
>>> t ^. slice @[0,0,0] @[2,2,2]
Tensor'2'2'2 [[[  0,  1]
              ,[  4,  5]]
             ,[[ 12, 13]
              ,[ 16, 17]]]
>>> set (slice @[0,0,0] @[2,2,2]) zero t
Tensor'2'3'4 [[[  0,  0,  2,  3]
              ,[  0,  0,  6,  7]
              ,[  8,  9, 10, 11]]
             ,[[  0,  0, 14, 15]
              ,[  0,  0, 18, 19]
              ,[ 20, 21, 22, 23]]]

type Slice startIndex sliceDims dims e = (IsTensor dims e, IsTensor (NormalizeDims sliceDims) e, GetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims), SetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims)) Source #

Constraints for slice function.

getSlice Source #

Arguments

:: GetSlice startIndex sliceDims dims e 
=> Tensor dims e 
-> Tensor (NormalizeDims sliceDims) e 

Extract slice of shape sliceDims from a tensor of shape dims starting at startIndex for each axis.

type GetSlice startIndex sliceDims dims e = (IsTensor dims e, IsTensor (NormalizeDims sliceDims) e, GetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims)) Source #

Constraints for getSlice.

getSliceElems Source #

Arguments

:: GetSliceElems startIndex sliceDims dims e 
=> Tensor dims e 
-> [e] 

Same as slice but returns list of elements instead of tensor data type.

type GetSliceElems startIndex sliceDims dims e = (IsTensor dims e, GetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims)) Source #

Constraints for getSliceElems.

setSlice Source #

Arguments

:: SetSlice startIndex sliceDims dims e 
=> Tensor dims e

The tensor.

-> Tensor (NormalizeDims sliceDims) e

New slice.

-> Tensor dims e 

Set elements of the slice.

type SetSlice startIndex sliceDims dims e = (IsTensor dims e, IsTensor (NormalizeDims sliceDims) e, SetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims)) Source #

Constraints for setSlice.

setSliceElems Source #

Arguments

:: SetSliceElems startIndex sliceDims dims e 
=> Tensor dims e

The tensor.

-> [e]

New elements of the slice.

-> Maybe (Tensor dims e) 

Like setSlice but takes a list of elements instead of a tensor. Returns Nothing if list has less than ElemsNumber sliceDims elements.

type SetSliceElems startIndex sliceDims dims e = (IsTensor dims e, SetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims)) Source #

Constraints for setSliceElems.

mapSliceElems Source #

Arguments

:: MapSliceElems startIndex sliceDims dims e 
=> Tensor dims e

The tensor.

-> (e -> e)

The mapping function.

-> Tensor dims e 

Modify slice elements with a function.

type MapSliceElems startIndex sliceDims dims e = (IsTensor dims e, GetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims), SetSliceElemsWrk (ElemsInSlice startIndex sliceDims dims), Map (ElemsNumber sliceDims)) Source #

Constraints for mapSliceElems.

Constraints for instances

type MonoFunctorCtx (dims :: [Nat]) e = (IsTensor dims e, Map (ElemsNumber dims)) Source #

Constraints for MonoFunctor instance for Tensor dims e.

type MonoFoldableCtx (dims :: [Nat]) e = (IsTensor dims e, Foldr (ElemsNumber dims), Foldl (ElemsNumber dims), Foldr1 (ElemsNumber dims), Foldl1 (ElemsNumber dims)) Source #

Constraints for MonoFoldable instance for Tensor dims e.

type MonoTraversableCtx (dims :: [Nat]) e = (IsTensor dims e, Map (ElemsNumber dims), Foldr (ElemsNumber dims), Foldl (ElemsNumber dims), Foldr1 (ElemsNumber dims), Foldl1 (ElemsNumber dims)) Source #

Constraints for MonoTraversable instance for Tensor dims e.

type MonoZipCtx (dims :: [Nat]) e = (IsTensor dims e, Map (ElemsNumber dims), ZipWith (ElemsNumber dims), Zip (ElemsNumber dims), Unzip (ElemsNumber dims)) Source #

Constraints for MonoZip instance for Tensor dims e.

Note: at the moment(GHC-8.2.1) the compiler generates suboptimal core for ounzip method. Expect it to be slower than most of the functions in the package.

Pointers

unsafeWithTensorPtr :: (IsTensor dims e, Storable e, KnownNat (ElemsNumber dims)) => Tensor dims e -> (Ptr e -> IO a) -> IO a Source #

Pass a pointer to the tensor's data to the IO action. The data may not be modified through the 'Ptr. Pointer may not be used after action is complete.