multilinear-0.4.0.0: src/Multilinear/Tensor.hs
{-|
Module : Multilinear.Tensor
Description : Tensors constructors (finitely- or infinitely-dimensional)
Copyright : (c) Artur M. Brodzki, 2018
License : BSD3
Maintainer : artur@brodzki.org
Stability : experimental
Portability : Windows/POSIX
- This module provides convenient constructors that generate a arbitrary finitely- or infinitely-dimensional tensors.
- Finitely-dimensional tensors provide much greater performance than inifitely-dimensional
-}
module Multilinear.Tensor (
-- * Generators
Multilinear.Tensor.generate
) where
import qualified Data.Vector as Boxed
import qualified Data.Vector.Unboxed as Unboxed
import Multilinear.Generic
import Multilinear.Index.Finite as Finite
invalidIndices :: (String, [Int]) -> (String, [Int]) -> String
invalidIndices us ds = "Indices and its sizes incompatible, upper indices: " ++ show us ++", lower indices: " ++ show ds
{-| Generate tensor composed of other tensors -}
generate :: (
Num a, Unboxed.Unbox a
) => (String,[Int]) -- ^ Upper indices names (one character per index) and its sizes
-> (String,[Int]) -- ^ Lower indices names (one character per index) and its sizes
-> ([Int] -> [Int] -> Tensor a) -- ^ Generator function (f [u1,u2,...] [d1,d2,...] returns a tensor element at t [u1,u2,...] [d1,d2,...])
-> Tensor a -- ^ Generated tensor
-- If no indices are given, generate a tensor by using generator function
generate ([],[]) ([],[]) f = f [] []
-- If many indices are given, first generate upper indices recursively from indices list
generate (u:us,s:size) d f =
FiniteTensor (Contravariant s [u]) $ Boxed.generate s (\x -> generate (us,size) d (\uss dss -> f (x:uss) dss) )
-- After upper indices, generate lower indices recursively from indices list
generate u (d:ds,s:size) f =
FiniteTensor (Covariant s [d]) $ Boxed.generate s (\x -> generate u (ds,size) (\uss dss -> f uss (x:dss)) )
-- If there are indices without size or sizes without names, throw an error
generate us ds _ = error $ invalidIndices us ds