packages feed

multilinear 0.2.3.0 → 0.3.0.0

raw patch · 15 files changed

+422/−739 lines, 15 filesdep +weighsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: weigh

API changes (from Hackage documentation)

- Multilinear.Class: iMap :: Accessible t a => ([Int] -> a -> b) -> t a -> t b
- Multilinear.Class: infix 8 $|
- Multilinear.Class: infixl 9 $$|
- Multilinear.Form: const' :: Num a => String -> a -> Tensor a
- Multilinear.Form: fromIndices' :: Num a => String -> (Int -> a) -> Tensor a
- Multilinear.Generic: Err :: String -> Tensor a
- Multilinear.Generic: FiniteTensor :: Index -> Vector (Tensor a) -> Tensor a
- Multilinear.Generic: InfiniteTensor :: Index -> [Tensor a] -> Tensor a
- Multilinear.Generic: Scalar :: a -> Tensor a
- Multilinear.Generic: SimpleFinite :: Index -> Vector a -> Tensor a
- Multilinear.Generic: [errMessage] :: Tensor a -> String
- Multilinear.Generic: [scalarVal] :: Tensor a -> a
- Multilinear.Generic: [tensorFiniteIndex] :: Tensor a -> Index
- Multilinear.Generic: [tensorInfiniteIndex] :: Tensor a -> Index
- Multilinear.Generic: [tensorScalars] :: Tensor a -> Vector a
- Multilinear.Generic: [tensorsFinite] :: Tensor a -> Vector (Tensor a)
- Multilinear.Generic: [tensorsInfinite] :: Tensor a -> [Tensor a]
- Multilinear.Generic: instance (GHC.Num.Num a, Data.Bits.Bits a) => Data.Bits.Bits (Multilinear.Generic.Tensor a)
- Multilinear.Generic: instance (GHC.Show.Show a, GHC.Num.Num a) => GHC.Show.Show (Multilinear.Generic.Tensor a)
- Multilinear.Generic: instance GHC.Base.Functor Multilinear.Generic.Tensor
- Multilinear.Generic: instance GHC.Classes.Eq a => GHC.Classes.Eq (Multilinear.Generic.Tensor a)
- Multilinear.Generic: instance GHC.Classes.Ord a => GHC.Classes.Ord (Multilinear.Generic.Tensor a)
- Multilinear.Generic: instance GHC.Float.Floating a => GHC.Float.Floating (Multilinear.Generic.Tensor a)
- Multilinear.Generic: instance GHC.Num.Num a => GHC.Num.Num (Multilinear.Generic.Tensor a)
- Multilinear.Generic: instance GHC.Num.Num a => Multilinear.Class.Accessible Multilinear.Generic.Tensor a
- Multilinear.Generic: instance GHC.Num.Num a => Multilinear.Class.Multilinear Multilinear.Generic.Tensor a
- Multilinear.Generic: instance GHC.Real.Fractional a => GHC.Real.Fractional (Multilinear.Generic.Tensor a)
- Multilinear.Generic: isInfiniteTensor :: Tensor a -> Bool
- Multilinear.Generic: mergeScalars :: Tensor a -> Tensor a
+ Multilinear.Class: infix 9 $|
+ Multilinear.Class: infixl 4 .-.
+ Multilinear.Class: infixl 5 .*.
+ Multilinear.Class: infixl 6 <<<|
+ Multilinear.Generic: [FiniteTensor] :: {tensorFiniteIndex :: Index " Finite index "Mutltilinear.Index.Finite" of tensor ", tensorsFinite :: Vector (Tensor a) " Array of tensors on deeper recursion level "} -> Tensor a
+ Multilinear.Generic: [Scalar] :: {scalarVal :: a} -> Tensor a
+ Multilinear.Generic: [SimpleFinite] :: {tensorFiniteIndex :: Index, tensorScalars :: Vector a} -> Tensor a
+ Multilinear.Generic: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Float.Floating a, Control.DeepSeq.NFData a) => GHC.Float.Floating (Multilinear.Generic.Tensor a)
+ Multilinear.Generic: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Num.Num a, Control.DeepSeq.NFData a) => GHC.Num.Num (Multilinear.Generic.Tensor a)
+ Multilinear.Generic: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Num.Num a, Control.DeepSeq.NFData a) => Multilinear.Class.Accessible Multilinear.Generic.Tensor a
+ Multilinear.Generic: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Num.Num a, Control.DeepSeq.NFData a) => Multilinear.Class.Multilinear Multilinear.Generic.Tensor a
+ Multilinear.Generic: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Real.Fractional a, Control.DeepSeq.NFData a) => GHC.Real.Fractional (Multilinear.Generic.Tensor a)
+ Multilinear.Generic: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Show.Show a, GHC.Num.Num a, Control.DeepSeq.NFData a) => GHC.Show.Show (Multilinear.Generic.Tensor a)
+ Multilinear.Generic: instance (GHC.Classes.Eq a, Data.Vector.Unboxed.Base.Unbox a) => GHC.Classes.Eq (Multilinear.Generic.Tensor a)
+ Multilinear.Generic: instance (GHC.Classes.Ord a, Data.Vector.Unboxed.Base.Unbox a) => GHC.Classes.Ord (Multilinear.Generic.Tensor a)
- Multilinear.Class: class (Num (t a), Functor t) => Multilinear t a
+ Multilinear.Class: class (Unbox a, Num (t a)) => Multilinear t a
- Multilinear.Class: infixl 7 \/
+ Multilinear.Class: infixl 7 $$|
- Multilinear.Class: infixl 8 .*
+ Multilinear.Class: infixl 8 \/
- Multilinear.Class: map :: Multilinear t a => (a -> b) -> t a -> t b
+ Multilinear.Class: map :: (Multilinear t a, Unbox b) => (a -> b) -> t a -> t b
- Multilinear.Form: const :: Num a => String -> Int -> a -> Tensor a
+ Multilinear.Form: const :: (Num a, Unbox a) => String -> Int -> a -> Tensor a
- Multilinear.Form: fromIndices :: Num a => String -> Int -> (Int -> a) -> Tensor a
+ Multilinear.Form: fromIndices :: (Num a, Unbox a) => String -> Int -> (Int -> a) -> Tensor a
- Multilinear.Generic: (!) :: Tensor a -> Int -> Tensor a
+ Multilinear.Generic: (!) :: Unbox a => Tensor a -> Int -> Tensor a
- Multilinear.Generic: _elemByElem :: Num a => Tensor a -> Tensor a -> (a -> a -> a) -> (Tensor a -> Tensor a -> Tensor a) -> Tensor a
+ Multilinear.Generic: _elemByElem :: (Num a, Unbox a, NFData a) => Tensor a -> Tensor a -> (a -> a -> a) -> (Tensor a -> Tensor a -> Tensor a) -> Tensor a
- Multilinear.Generic: _standardize :: Num a => Tensor a -> Tensor a
+ Multilinear.Generic: _standardize :: (Num a, Unbox a, NFData a) => Tensor a -> Tensor a
- Multilinear.Generic: dot :: Num a => Tensor a -> Tensor a -> Tensor a
+ Multilinear.Generic: dot :: (Num a, Unbox a, NFData a) => Tensor a -> Tensor a -> Tensor a
- Multilinear.Generic: isFiniteTensor :: Tensor a -> Bool
+ Multilinear.Generic: isFiniteTensor :: Unbox a => Tensor a -> Bool
- Multilinear.Generic: isScalar :: Tensor a -> Bool
+ Multilinear.Generic: isScalar :: Unbox a => Tensor a -> Bool
- Multilinear.Generic: isSimple :: Tensor a -> Bool
+ Multilinear.Generic: isSimple :: Unbox a => Tensor a -> Bool
- Multilinear.Generic: tensorIndex :: Tensor a -> TIndex
+ Multilinear.Generic: tensorIndex :: Unbox a => Tensor a -> TIndex
- Multilinear.Matrix: const :: Num a => String -> Int -> Int -> a -> Tensor a
+ Multilinear.Matrix: const :: (Num a, Unbox a) => String -> Int -> Int -> a -> Tensor a
- Multilinear.Matrix: fromIndices :: Num a => String -> Int -> Int -> (Int -> Int -> a) -> Tensor a
+ Multilinear.Matrix: fromIndices :: (Num a, Unbox a) => String -> Int -> Int -> (Int -> Int -> a) -> Tensor a
- Multilinear.NForm: const :: Num a => String -> [Int] -> a -> Tensor a
+ Multilinear.NForm: const :: (Num a, Unbox a) => String -> [Int] -> a -> Tensor a
- Multilinear.NForm: cross :: Num a => String -> Int -> Tensor a
+ Multilinear.NForm: cross :: (Num a, Unbox a) => String -> Int -> Tensor a
- Multilinear.NForm: dot :: Num a => String -> Int -> Tensor a
+ Multilinear.NForm: dot :: (Num a, Unbox a) => String -> Int -> Tensor a
- Multilinear.NForm: fromIndices :: Num a => String -> [Int] -> ([Int] -> a) -> Tensor a
+ Multilinear.NForm: fromIndices :: (Num a, Unbox a) => String -> [Int] -> ([Int] -> a) -> Tensor a
- Multilinear.NVector: const :: Num a => String -> [Int] -> a -> Tensor a
+ Multilinear.NVector: const :: (Num a, Unbox a) => String -> [Int] -> a -> Tensor a
- Multilinear.NVector: fromIndices :: Num a => String -> [Int] -> ([Int] -> a) -> Tensor a
+ Multilinear.NVector: fromIndices :: (Num a, Unbox a) => String -> [Int] -> ([Int] -> a) -> Tensor a
- Multilinear.Tensor: const :: Num a => (String, [Int]) -> (String, [Int]) -> a -> Tensor a
+ Multilinear.Tensor: const :: (Num a, Unbox a) => (String, [Int]) -> (String, [Int]) -> a -> Tensor a
- Multilinear.Tensor: fromIndices :: Num a => (String, [Int]) -> (String, [Int]) -> ([Int] -> [Int] -> a) -> Tensor a
+ Multilinear.Tensor: fromIndices :: (Num a, Unbox a) => (String, [Int]) -> (String, [Int]) -> ([Int] -> [Int] -> a) -> Tensor a
- Multilinear.Tensor: generate :: Num a => (String, [Int]) -> (String, [Int]) -> ([Int] -> [Int] -> Tensor a) -> Tensor a
+ Multilinear.Tensor: generate :: (Num a, Unbox a) => (String, [Int]) -> (String, [Int]) -> ([Int] -> [Int] -> Tensor a) -> Tensor a
- Multilinear.Vector: const :: Num a => String -> Int -> a -> Tensor a
+ Multilinear.Vector: const :: (Num a, Unbox a) => String -> Int -> a -> Tensor a
- Multilinear.Vector: fromIndices :: Num a => String -> Int -> (Int -> a) -> Tensor a
+ Multilinear.Vector: fromIndices :: (Num a, Unbox a) => String -> Int -> (Int -> a) -> Tensor a

Files

ChangeLog.md view
@@ -1,4 +1,11 @@-# 0.2.2.2, 2018-11-02
+# 0.3.0.0, 2018-11-14
+- moved to Vector.Unboxed, to improve performance
+- simplified error handling - removed separate Err Tensor value
+- temporarily removed Infinite tensors constructors and Generic
+- added memory benchmark
+- added simple unit tests
+
+# 0.2.3, 2018-11-02
 - fixed conflicting dependencies
 - added criterion benchmarks
 
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple
-main = defaultMain
+import Distribution.Simple+main = defaultMain
− benchmark/Bench.hs
@@ -1,30 +0,0 @@-{-|
-Module      : Bench
-Description : Benchmark of Multilinear library
-Copyright   : (c) Artur M. Brodzki, 2018
-License     : BSD3
-Maintainer  : artur@brodzki.org
-Stability   : experimental
-Portability : Windows/POSIX
-
--}
-
-module Main (
-    main
-) where
-
-import           Criterion.Main
-import qualified Multilinear.Matrix                  as Matrix
-
-gen :: Int -> Int -> Double
-gen j k = sin (fromIntegral j) + cos (fromIntegral k)
-
-sizedMatrixBench :: Int -> Benchmark
-sizedMatrixBench s = 
-    bench ((show s) ++ "x" ++ (show s)) $ 
-        nf ((Matrix.fromIndices "ij" s s gen) *) (Matrix.fromIndices "jk" s s gen)
-
-main :: IO ()
-main = defaultMain [
-    bgroup "matrix multiplication" $ sizedMatrixBench <$> [10, 20, 50, 80, 160, 320]
-    ]
+ benchmark/memory/Bench.hs view
@@ -0,0 +1,37 @@+{-|
+Module      : Bench
+Description : Benchmark of Multilinear library
+Copyright   : (c) Artur M. Brodzki, 2018
+License     : BSD3
+Maintainer  : artur@brodzki.org
+Stability   : experimental
+Portability : Windows/POSIX
+
+-}
+
+module Main (
+    main
+) where
+
+import           Weigh
+import qualified Multilinear.Matrix as Matrix
+import qualified Multilinear.Vector as Vector
+
+gen :: Int -> Int -> Double
+gen j k = sin (fromIntegral j) + cos (fromIntegral k)
+
+main :: IO ()
+main = mainWith (do
+    setColumns [Case, Allocated, GCs, Live, Max]
+    func "vector 1 elem generation" (Vector.fromIndices "i" 1) id
+    func "vector 2 elem generation" (Vector.fromIndices "i" 2) id
+    func "vector 3 elem generation" (Vector.fromIndices "i" 3) id
+    func "matrix 1024 x 1024 generation" 
+        (Matrix.fromIndices "ij" 1024 1024) gen
+    func "matrix 10214 x 1024 addition" 
+        (+ Matrix.fromIndices "ab" 1024 1024 gen) 
+        (Matrix.fromIndices "ab" 1024 1024 (\a b -> fromIntegral a + fromIntegral b))
+    func "matrix 40 x 60,000 multiplication" 
+        (* Matrix.fromIndices "jk" 60000 40 gen) 
+        (Matrix.fromIndices "ij" 40 60000 gen)
+    )
+ benchmark/time/Bench.hs view
@@ -0,0 +1,36 @@+{-|
+Module      : Bench
+Description : Benchmark of Multilinear library
+Copyright   : (c) Artur M. Brodzki, 2018
+License     : BSD3
+Maintainer  : artur@brodzki.org
+Stability   : experimental
+Portability : Windows/POSIX
+
+-}
+
+module Main (
+    main
+) where
+
+import           Criterion.Main
+import qualified Multilinear.Matrix                  as Matrix
+
+gen :: Int -> Int -> Double
+gen j k = sin (fromIntegral j) + cos (fromIntegral k)
+
+sizedMatrixMultBench :: Int -> Benchmark
+sizedMatrixMultBench s = 
+    bench ((show s) ++ "x" ++ (show s)) $ 
+        nf ((Matrix.fromIndices "ij" s s gen) *) (Matrix.fromIndices "jk" s s gen)
+
+sizedMatrixAddBench :: Int -> Benchmark
+sizedMatrixAddBench s = 
+    bench ((show s) ++ "x" ++ (show s)) $ 
+        nf ((Matrix.fromIndices "ij" s s gen) +) (Matrix.fromIndices "ij" s s gen)
+
+main :: IO ()
+main = defaultMain [
+    bgroup "matrix multiplication" $ sizedMatrixMultBench <$> [64, 128, 256, 512],
+    bgroup "matrix addition" $ sizedMatrixAddBench <$> [64, 128, 256, 512]
+    ]
multilinear.cabal view
@@ -1,13 +1,11 @@-cabal-version: 1.12
---- This file has been generated from package.yaml by hpack version 0.31.0.+-- This file has been generated from package.yaml by hpack version 0.28.2.
 -- -- see: https://github.com/sol/hpack ----- hash: 7041c3d6136ceb4cb94868756b2c05085d09b4eb61eadb530dee0253bb02434c+-- hash: 9a78adbc87a7e540f962949e44f5f5e34d8cbdfd6a8e7b8b77c7c70a029e6df0  name:           multilinear-version:        0.2.3.0+version:        0.3.0.0 synopsis:       Comprehensive and efficient (multi)linear algebra implementation. description:    Comprehensive and efficient (multi)linear algebra implementation, based on generic tensor formalism and concise Ricci-Curbastro index syntax. More information available on GitHub: <https://github.com/ArturB/multilinear#readme> category:       Machine learning@@ -19,9 +17,10 @@ license:        BSD3 license-file:   LICENSE build-type:     Simple+cabal-version:  >= 1.10 extra-source-files:-    README.md     ChangeLog.md+    README.md  source-repository head   type: git@@ -45,8 +44,8 @@       Paths_multilinear   hs-source-dirs:       src-  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances MultiParamTypeClasses-  ghc-options: -O2 -Wall+  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances GADTs MultiParamTypeClasses ScopedTypeVariables StandaloneDeriving+  ghc-options: -O2 -W   build-depends:       base >=4.7 && <5     , containers@@ -57,30 +56,45 @@     , vector   default-language: Haskell2010 -test-suite multilinear-test+test-suite all   type: exitcode-stdio-1.0   main-is: Spec.hs   other-modules:       Paths_multilinear   hs-source-dirs:       test-  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances MultiParamTypeClasses-  ghc-options: -O2 -Wall -threaded -rtsopts -with-rtsopts=-N+  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances GADTs MultiParamTypeClasses ScopedTypeVariables StandaloneDeriving+  ghc-options: -O2 -W -threaded -rtsopts -with-rtsopts=-N   build-depends:       base >=4.7 && <5-    , criterion+    , deepseq     , multilinear   default-language: Haskell2010 -benchmark multilinear-bench+benchmark memory   type: exitcode-stdio-1.0   main-is: Bench.hs   other-modules:       Paths_multilinear   hs-source-dirs:-      benchmark-  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances MultiParamTypeClasses-  ghc-options: -O2 -Wall -threaded -rtsopts -with-rtsopts=-N+      benchmark/memory+  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances GADTs MultiParamTypeClasses ScopedTypeVariables StandaloneDeriving+  ghc-options: -O2 -W -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , multilinear+    , weigh+  default-language: Haskell2010++benchmark time+  type: exitcode-stdio-1.0+  main-is: Bench.hs+  other-modules:+      Paths_multilinear+  hs-source-dirs:+      benchmark/time+  default-extensions: DeriveGeneric FlexibleContexts FlexibleInstances GADTs MultiParamTypeClasses ScopedTypeVariables StandaloneDeriving+  ghc-options: -O2 -W -threaded -rtsopts -with-rtsopts=-N   build-depends:       base >=4.7 && <5     , criterion
src/Multilinear/Class.hs view
@@ -149,54 +149,56 @@ 
 import           Data.Maybe
 import           Data.Set
+import qualified Data.Vector.Unboxed as Unboxed
 import           Multilinear.Index
 
 {-| Multidimensional array treated as multilinear map - tensor -}
 class (
-  Num (t a),     -- Tensors may be added, subtracted and multiplicated
-  Functor t      -- Tensor should be a Functor for convenience
+  Unboxed.Unbox a,
+  Num (t a)     -- Tensors may be added, subtracted and multiplicated
   ) => Multilinear t a where
 
     {-| Add scalar @a@ to each element of tensor @t@ -}
-    infixl 7 +.
+    infixl 4 +.
     (+.) :: a -> t a -> t a
 
     {-| Subtract each element of tensor @t@ from scalar scalar left -}
-    infixl 7 -.
+    infixl 4 -.
     (-.) :: a -> t a -> t a
 
     {-| Multiply scalar @a@ by each element of tensor @t@ -}
-    infixl 8 *.
+    infixl 5 *.
     (*.) :: a -> t a -> t a
 
     {-| Add each element of tensor @t@ to scalar @a@ -}
-    infixl 7 .+
+    infixl 4 .+
     (.+) :: t a -> a -> t a
 
     {-| Subtract scalar @a@ from each element of tensor @t@ -}
-    infixl 7 .-
+    infixl 4 .-
     (.-) :: t a -> a -> t a
 
     {-| Multiply each element of tensor @t@ by scalar @a@ -}
-    infixl 8 .*
+    infixl 5 .*
     (.*) :: t a -> a -> t a
 
     {-| Tensor adding - functionally equal to Num (+) but more efficient -}
-    infixl 7 .+.
+    infixl 4 .+.
     (.+.) :: t a -> t a -> t a
 
     {-| Tensor subtracting - functionally equal to Num (-) but more efficient -}
-    infixl 7 .-.
+    infixl 4 .-.
     (.-.) :: t a -> t a -> t a
 
     {-| Tensor multiplication - functionally equal to Num (*) but more efficient -}
-    infixl 7 .*.
+    infixl 5 .*.
     (.*.) :: t a -> t a -> t a
 
     {-| List of all tensor indices -}
     indices :: t a -> [TIndex]
 
     {-| List of tensor indices names -}
+    {-# INLINE indicesNames #-}
     indicesNames :: t a -> [String]
     indicesNames t = indexName <$> indices t
 
@@ -208,33 +210,39 @@     size :: t a -> String -> Int
 
     {-| Check if tensors are equivalent (have same indices but in different order) -}
+    {-# INLINE equiv #-}
     equiv :: t a -> t a -> Bool
     equiv t1 t2 = Data.Set.fromList (indices t1) == Data.Set.fromList (indices t2)
 
     {-| Infix equivalent of 'equiv'. Has low priority equal to 1. |-}
+    {-# INLINE (|==|) #-}
     infixl 1 |==|
     (|==|) :: t a -> t a -> Bool
     t1 |==| t2 = equiv t1 t2
 
     {-| @t $| "ij" "kl"@ renames upper indices of tensor @t@ to @ij@ and lower indices to @kl@ -}
-    infix 8 $|
+    infix 9 $|
     ($|) :: t a -> (String,String) -> t a
 
     {-| @raise t "i"@ raises an index @i@ of tensor @t@ -}
+    {-# INLINE raise #-}
     raise :: t a -> String -> t a
     raise t i = t /\ i
 
     {-| Infix equivalent of 'raise' -}
-    infixl 7 /\
+    {-# INLINE (/\) #-}
+    infixl 8 /\
     (/\) :: t a -> String -> t a
     t /\ i = raise t i
 
     {-| @lower t "i"@ lowers an index @i@ of tensor @t@ -}
+    {-# INLINE lower #-}
     lower :: t a -> String -> t a
     lower t i = t \/ i
 
     {-| Infix equivalent of 'lower' -}
-    infixl 7 \/
+    {-# INLINE (\/) #-}
+    infixl 8 \/
     (\/) :: t a -> String -> t a
     t \/ i = lower t i
 
@@ -244,6 +252,7 @@     {-| Shift tensor index right -}
     {-| @shiftRight t "i"@ moves index @i@ of tensor @t@ one level depeer in recursion.
         Elements of tensor as indexed with indices names becomes unchanged. -}
+    {-# INLINE shiftRight #-}
     shiftRight :: t a -> String -> t a
     -- ^ Right shift of an index is equivalent to left shift of its successor in recursion @s@, if only @s@ exists, so:
     -- Given a tensor @t[i1,i2,i3,...]@: @shiftRight t "i2" == t[i1,i3,i2,...] == shiftLeft t "i3"@
@@ -256,24 +265,28 @@ 
     {-| Infix equivalent of 'shiftRight' -}
     {-| @t |>> "i"@ moves index @i@ of tensor @t@ one level depeer in recursion -}
-    infixl 9 |>>
+    {-# INLINE (|>>) #-}
+    infixl 6 |>>
     (|>>) :: t a -> String -> t a
     t |>> n = shiftRight t n
 
     {-| Shift tensor index rightmost -}
     {-| @shiftRightmost t "i"@ moves index @i@ of tensor @t@ to the deepest level in recursion.
         Elements of tensor as indexed with indices names becomes unchanged.  -}
+    {-# INLINE shiftRightmost #-}
     shiftRightmost :: t a -> String -> t a
     shiftRightmost t n = until (\x -> n == last (indicesNames x)) (|>> n) t
 
     {-| Infix equivalent of 'shiftRightmost' -}
     {-| @t |>>> "i"@ moves index @i@ of tensor @t@ to the deepest level in recursion -}
-    infixl 9 |>>>
+    {-# INLINE (|>>>) #-}
+    infixl 6 |>>>
     (|>>>) :: t a -> String -> t a
     t |>>> n = shiftRightmost t n
 
     {-| Shift tensor index left. Elements of tensor as indexed with indices names becomes unchanged. -}
     {-| @shiftLeft t "i"@ moves index @i@ of tensor @t@ one level up in recursion -}
+    {-# INLINE shiftLeft #-}
     shiftLeft :: t a -> String -> t a
     -- ^ Left shift of an index is equivalent to right shift of its predecessor in recursion @p@, if only @p@ exists, so:
     -- Given a tensor t[i1,i2,i3,...]: @shiftLeft t "i3" == t[i1,i3,i2,...] == shiftRight t "i2"@
@@ -286,25 +299,27 @@ 
     {-| Infix equivalent to 'shiftLeft' -}
     {-| @t <<| "i"@ moves index @i@ of tensor @t@ one level up in recursion -}
-    infixl 9 <<|
+    {-# INLINE (<<|) #-}
+    infixl 6 <<|
     (<<|) :: t a -> String -> t a
     t <<| n = shiftLeft t n
 
     {-| Shift tensor index leftmost. Elements of tensor as indexed with indices names becomes unchanged. -}
     {-| @shiftLeftmost t "i"@ moves index @i@ of tensor @t@ to the first level in recursion -}
+    {-# INLINE shiftLeftmost #-}
     shiftLeftmost :: t a -> String -> t a
     shiftLeftmost t n = until (\x -> n == head (indicesNames x)) (<<| n) t
 
     {-| Infix equivalent of 'shiftLeftmost' -}
     {-| @t <<<| "i"@ moves index @i@ of tensor @t@ to the first level in recursion -}
-    infixl 9 <<<|
+    {-# INLINE (<<<|) #-}
+    infixl 6 <<<|
     (<<<|) :: t a -> String -> t a
     t <<<| n = shiftLeftmost t n
 
     {-| Simple mapping -}
     {-| @map f t@ returns tensor @t2@ in which @t2[i1,i2,...] = f t[i1,i2,...]@ -}
-    map :: (a -> b) -> t a -> t b
-    map = fmap
+    map :: Unboxed.Unbox b => (a -> b) -> t a -> t b
 
 
 {-| If container on which tensor instance is built, allows for random access of its elements, then the tensor can be instanced as Accessible -}
@@ -318,11 +333,7 @@     el :: t a -> (String,[Int]) -> t a
 
     {-| Infix equivalent for el -}
-    infixl 9 $$|
+    {-# INLINE ($$|) #-}
+    infixl 7 $$|
     ($$|) :: t a -> (String,[Int]) -> t a
     t $$| is = el t is
-
-    {-| Mapping with indices - mapping function takes not only a tensor element value but also its indices in tensor -}
-    {-| @iMap f t@ return tensor @t2@ in which @t2[i1,i2,...] = f [i1,i2,...] t[i1,i2,...]@ -}
-    iMap :: ([Int] -> a -> b) -> t a -> t b
-    -- // TODO
src/Multilinear/Form.hs view
@@ -20,15 +20,12 @@   Multilinear.Form.randomDouble,
    Multilinear.Form.randomDoubleSeed,
   Multilinear.Form.randomInt, 
-  Multilinear.Form.randomIntSeed,
-  -- ** Infinite functionals
-  Multilinear.Form.fromIndices', 
-  Multilinear.Form.const'
+  Multilinear.Form.randomIntSeed
 ) where
 
 import           Control.Monad.Primitive
+import qualified Data.Vector.Unboxed        as Unboxed
 import           Multilinear.Generic
-import           Multilinear.Index.Infinite as Infinite
 import           Multilinear.Tensor         as Tensor
 import           Statistics.Distribution
 
@@ -38,28 +35,28 @@ -- * Finite functional generators
 
 {-| Generate linear functional as function of indices -}
-{-# INLINE fromIndices #-}
+
 fromIndices :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String        -- ^ Index name (one character)
     -> Int           -- ^ Number of elements
     -> (Int -> a)    -- ^ Generator function - returns a linear functional component at index @i@
     -> Tensor a      -- ^ Generated linear functional
 
 fromIndices [i] s f = Tensor.fromIndices ([],[]) ([i],[s]) $ \[] [x] -> f x
-fromIndices _ _ _ = Err invalidIndices
+fromIndices _ _ _ = error invalidIndices
 
 {-| Generate linear functional with all components equal to some @v@ -}
-{-# INLINE Multilinear.Form.const #-}
+
 const :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String      -- ^ Index name (one character)
     -> Int         -- ^ Number of elements
     -> a           -- ^ Value of each element
     -> Tensor a    -- ^ Generated linear functional
 
 const [i] s = Tensor.const ([],[]) ([i],[s])
-const _ _ = \_ -> Err invalidIndices
+const _ _ = \_ -> error invalidIndices
 
 {-| Generate linear functional with random real components with given probability distribution.
 The functional is wrapped in the IO monad. -}
@@ -74,7 +71,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDouble #-}
+
 randomDouble :: (
     ContGen d
   ) => String              -- ^ Index name (one character)
@@ -83,7 +80,7 @@     -> IO (Tensor Double)  -- ^ Generated linear functional
 
 randomDouble [i] s = Tensor.randomDouble ([],[]) ([i],[s])
-randomDouble _ _ = \_ -> return $ Err invalidIndices
+randomDouble _ _ = \_ -> return $ error invalidIndices
 
 {-| Generate linear functional with random integer components with given probability distribution.
 The functional is wrapped in the IO monad. -}
@@ -92,7 +89,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomInt #-}
+
 randomInt :: (
     DiscreteGen d
   ) => String             -- ^ Index name (one character)
@@ -101,7 +98,7 @@     -> IO (Tensor Int)    -- ^ Generated linear functional
 
 randomInt [i] s = Tensor.randomInt ([],[]) ([i],[s])
-randomInt _ _ = \_ -> return $ Err invalidIndices
+randomInt _ _ = \_ -> return $ error invalidIndices
 
 {-| Generate linear functional with random real components with given probability distribution and given seed.
 The functional is wrapped in a monad. -}
@@ -116,7 +113,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDoubleSeed #-}
+
 randomDoubleSeed :: (
     ContGen d, PrimMonad m
   ) => String                 -- ^ Index name (one character)
@@ -126,7 +123,7 @@     -> m (Tensor Double)      -- ^ Generated linear functional
 
 randomDoubleSeed [i] s = Tensor.randomDoubleSeed ([],[]) ([i],[s])
-randomDoubleSeed _ _ = \_ _ -> return $ Err invalidIndices
+randomDoubleSeed _ _ = \_ _ -> return $ error invalidIndices
 
 {-| Generate linear functional with random integer components with given probability distribution and given seed.
 The functional is wrapped in a monad. -}
@@ -135,7 +132,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomIntSeed #-}
+
 randomIntSeed :: (
     DiscreteGen d, PrimMonad m
   ) => String                -- ^ Index name (one character)
@@ -145,29 +142,5 @@     -> m (Tensor Int)        -- ^ Generated linear functional
 
 randomIntSeed [i] s = Tensor.randomIntSeed ([],[]) ([i],[s])
-randomIntSeed _ _ = \_ _ -> return $ Err invalidIndices
-
-{-| Generate linear functional as function of indices -}
-{-# INLINE fromIndices' #-}
-fromIndices' :: (
-    Num a
-  ) => String        -- ^ Index name (one character)
-    -> (Int -> a)    -- ^ Generator function - returns a linear functional component at index @i@
-    -> Tensor a      -- ^ Generated linear functional
-
-fromIndices' i = case i of
-    [d] -> \f -> InfiniteTensor (Infinite.Covariant [d]) $ (Scalar . f) <$> [0..]
-    _   -> \_ -> Err invalidIndices
-
-{-| Generate linear functional with all components equal to some @v@ -}
-{-# INLINE Multilinear.Form.const' #-}
-const' :: (
-    Num a
-  ) => String      -- ^ Index name (one character)
-    -> a           -- ^ Value of each element
-    -> Tensor a    -- ^ Generated linear functional
-
-const' i = case i of
-    [d] -> \v -> InfiniteTensor (Infinite.Covariant [d]) $ (\_ -> Scalar v) <$> ([0..] :: [Int])
-    _   -> \_ -> Err invalidIndices
+randomIntSeed _ _ = \_ _ -> return $ error invalidIndices
 
src/Multilinear/Generic.hs view
@@ -12,22 +12,21 @@ -}
 
 module Multilinear.Generic (
-    Tensor(..), (!), mergeScalars,
-    isScalar, isSimple, isFiniteTensor, isInfiniteTensor,
+    Tensor(..), (!),
+    isScalar, isSimple, isFiniteTensor,
     dot, _elemByElem, contractionErr, tensorIndex, _standardize
 ) where
 
 import           Control.DeepSeq
-import           Data.Bits
 import           Data.Foldable
 import           Data.List
 import           Data.Maybe
 import qualified Data.Vector                as Boxed
+import qualified Data.Vector.Unboxed        as Unboxed
 import           GHC.Generics
 import           Multilinear.Class          as Multilinear
 import qualified Multilinear.Index          as Index
 import qualified Multilinear.Index.Finite   as Finite
-import qualified Multilinear.Index.Infinite as Infinite
 
 {-| ERROR MESSAGES -}
 incompatibleTypes :: String
@@ -36,148 +35,102 @@ scalarIndices :: String
 scalarIndices = "Scalar has no indices!"
 
-infiniteIndex :: String
-infiniteIndex = "Index is infinitely-dimensional!"
-
-infiniteTensor :: String
-infiniteTensor = "This tensor is infinitely-dimensional and cannot be printed!"
-
 indexNotFound :: String
 indexNotFound = "This tensor has not such index!"
 
 {-| Tensor defined recursively as scalar or list of other tensors -}
 {-| @c@ is type of a container, @i@ is type of index size and @a@ is type of tensor elements -}
-data Tensor a =
+data Tensor a where
     {-| Scalar -}
-    Scalar {
-        {-| value of scalar -}
+    Scalar :: {
         scalarVal :: a
-    } |
+    } -> Tensor a
     {-| Simple, one-dimensional finite tensor -}
-    SimpleFinite {
+    SimpleFinite :: {
         tensorFiniteIndex :: Finite.Index,
-        tensorScalars     :: Boxed.Vector a
-    } |
+        tensorScalars     :: Unboxed.Vector a
+    } -> Tensor a
     {-| Finite array of other tensors -}
-    FiniteTensor {
+    FiniteTensor :: {
         {-| Finite index "Mutltilinear.Index.Finite" of tensor -}
         tensorFiniteIndex :: Finite.Index,
         {-| Array of tensors on deeper recursion level -}
         tensorsFinite     :: Boxed.Vector (Tensor a)
-    } |
-    {-| Infinite list of other tensors -}
-    InfiniteTensor {
-        {-| Infinite index "Mutltilinear.Index.Infinite" of tensor -}
-        tensorInfiniteIndex :: Infinite.Index,
-        {-| Infinite list of tensors on deeper recursion level -}
-        tensorsInfinite     :: [Tensor a]
-    } |
-    {-| Operations on tensors may throw an error -}
-    Err {
-        {-| Error message -}
-        errMessage :: String
-    } deriving (Eq, Generic)
+    } -> Tensor a
+    deriving (Eq, Generic)
 
+
 {-| Return true if tensor is a scalar -}
 {-# INLINE isScalar #-}
-isScalar :: Tensor a -> Bool
+isScalar :: Unboxed.Unbox a => Tensor a -> Bool
 isScalar x = case x of
     Scalar _ -> True
     _        -> False
 
 {-| Return true if tensor is a simple tensor -}
 {-# INLINE isSimple #-}
-isSimple :: Tensor a -> Bool
+isSimple :: Unboxed.Unbox a => Tensor a -> Bool
 isSimple x = case x of
     SimpleFinite _ _ -> True
     _                -> False
 
 {-| Return True if tensor is a complex tensor -}
 {-# INLINE isFiniteTensor #-}
-isFiniteTensor :: Tensor a -> Bool
+isFiniteTensor :: Unboxed.Unbox a => Tensor a -> Bool
 isFiniteTensor x = case x of
     FiniteTensor _ _ -> True
     _                -> False
 
-{-| Return True if tensor is a infinite tensor -}
-{-# INLINE isInfiniteTensor #-}
-isInfiniteTensor :: Tensor a -> Bool
-isInfiniteTensor x = case x of
-    InfiniteTensor _ _ -> True
-    _                  -> False
-
-{- Return True if tensor is a error tensor -}
-{-# INLINE isErrTensor #-}
-isErrTensor :: Tensor a -> Bool
-isErrTensor x = case x of
-    Err _ -> True
-    _     -> False
-
 {-| Return generic tensor index -}
 {-# INLINE tensorIndex #-}
-tensorIndex :: Tensor a -> Index.TIndex
+tensorIndex :: Unboxed.Unbox a => Tensor a -> Index.TIndex
 tensorIndex x = case x of
     Scalar _           -> error scalarIndices
     SimpleFinite i _   -> Index.toTIndex i
     FiniteTensor i _   -> Index.toTIndex i
-    InfiniteTensor i _ -> Index.toTIndex i
-    Err msg            -> error msg
 
-{-| Return True if tensor has no elements -}
-{-# INLINE isEmptyTensor #-}
-isEmptyTensor :: Tensor a -> Bool
-isEmptyTensor x = case x of
-    Scalar _            -> False
-    SimpleFinite _ ts   -> Boxed.null ts
-    FiniteTensor _ ts   -> Boxed.null ts
-    InfiniteTensor _ ts -> null ts
-    Err _               -> False
-
-{-| Returns sample element of the tensor. Used to determine some features common for all elements, like bit-qualities. -}
-{-# INLINE firstElem #-}
-firstElem :: Tensor a -> a
-firstElem x = case x of
-    Scalar val          -> val
-    SimpleFinite _ ts   -> Boxed.head ts
-    FiniteTensor _ ts   -> firstElem $ Boxed.head ts
-    InfiniteTensor _ ts -> firstElem $ head ts
-    Err msg             -> error msg
-
 {-| Returns sample tensor on deeper recursion level.Used to determine some features common for all tensors -}
 {-# INLINE firstTensor #-}
-firstTensor :: Tensor a -> Tensor a
+firstTensor :: Unboxed.Unbox a => Tensor a -> Tensor a
 firstTensor x = case x of
     FiniteTensor _ ts   -> Boxed.head ts
-    InfiniteTensor _ ts -> Data.List.head ts
     _                   -> x
 
 {-| Recursive indexing on list tensor
     @t ! i = t[i]@ -}
 {-# INLINE (!) #-}
-(!) :: Tensor a      -- ^ tensor @t@
+(!) :: Unboxed.Unbox a => Tensor a      -- ^ tensor @t@
     -> Int           -- ^ index @i@
     -> Tensor a      -- ^ tensor @t[i]@
 t ! i = case t of
-    Scalar _            -> Err scalarIndices
-    Err msg             -> Err msg
-    SimpleFinite ind ts -> if i >= Finite.indexSize ind then error ("Index + " ++ show ind ++ " out of bonds!") else Scalar $ ts Boxed.! i
-    FiniteTensor ind ts -> if i >= Finite.indexSize ind then error ("Index + " ++ show ind ++ " out of bonds!") else ts Boxed.! i
-    InfiniteTensor _ ts -> ts !! i
+    Scalar _            -> error scalarIndices
+    SimpleFinite ind ts -> 
+        if i >= Finite.indexSize ind then 
+            error ("Index + " ++ show ind ++ " out of bonds!") 
+        else Scalar $ ts Unboxed.! i
+    FiniteTensor ind ts -> 
+        if i >= Finite.indexSize ind then 
+            error ("Index + " ++ show ind ++ " out of bonds!") 
+        else ts Boxed.! i
 
 -- NFData instance
 instance NFData a => NFData (Tensor a)
 
 -- move contravariant indices to lower recursion level
-_standardize :: Num a => Tensor a -> Tensor a
-_standardize tens = foldr' (\i t -> if Index.isContravariant i then t <<<| Index.indexName i else t) tens $ indices tens
+_standardize :: (Num a, Unboxed.Unbox a, NFData a) => Tensor a -> Tensor a
+_standardize tens = foldr' f tens $ indices tens
+    where 
+        f i t = if Index.isContravariant i then 
+            t <<<| Index.indexName i 
+        else t
 
 -- Print tensor
 instance (
-    Show a, Num a
+    Unboxed.Unbox a, Show a, Num a, NFData a
     ) => Show (Tensor a) where
 
     -- merge errors first and then print whole tensor
-    show = show' . _standardize . _mergeErr
+    show = show' . _standardize
         where
         show' x = case x of
             -- Scalar is showed simply as its value
@@ -185,71 +138,23 @@             -- SimpleFinite is shown dependent on its index...
             SimpleFinite index ts -> show index ++ "S: " ++ case index of
                 -- If index is contravariant, show tensor components vertically
-                Finite.Contravariant _ _ -> _showVertical ts
+                Finite.Contravariant _ _ -> "\n" ++ tail (Unboxed.foldl' (\string e -> string ++ "\n  |" ++ show e) "" ts)
                 -- If index is covariant or indifferent, show tensor compoments horizontally
-                _                        -> _showHorizontal ts
+                _                        -> "["  ++ tail (Unboxed.foldl' (\string e -> string ++ "," ++ show e) "" ts) ++ "]"
             -- FiniteTensor is shown dependent on its index...
             FiniteTensor index ts -> show index ++ "T: " ++ case index of
                 -- If index is contravariant, show tensor components vertically
-                Finite.Contravariant _ _ -> _showVertical ts
+                Finite.Contravariant _ _ -> "\n" ++ tail (Boxed.foldl' (\string e -> string ++ "\n  |" ++ show e) "" ts)
                 -- If index is covariant or indifferent, show tensor compoments horizontally
-                _                        -> _showHorizontal ts
-            -- Infinite tensor print erorr message as it cannot be fully shown
-            InfiniteTensor _ _ -> show infiniteTensor
-            -- Error prints its error message
-            Err msg -> show msg
-            
-        -- Merge many errors in tensor to the first one
-        _mergeErr x = case x of
-            -- Error tensor is passed further
-            Err msg -> Err msg
-            -- FiniteTensor is merged to first error on deeper recursion level
-            FiniteTensor _ ts ->
-                -- find first error if present
-                let err = Data.List.find isErrTensor (_mergeErr <$> ts)
-                -- and return this error if found, whole tensor otherwise
-                in fromMaybe x err
-            -- in other types of tensor cannot be any error
-            _ -> x
-
-        -- print container elements vertically
-        -- used to show contravariant components of tensor, which by convention are written vertically
-        _showVertical :: (Show a, Foldable c) => c a -> String
-        _showVertical container =
-            "\n" ++ tail (foldl' (\string e -> string ++ "\n  |" ++ show e) "" container)
-
-        -- print container elements horizontally
-        -- used to show covariant (or indifferent) components of tensor, which by convention are written horizontally
-        _showHorizontal :: (Show a, Foldable c) => c a -> String
-        _showHorizontal container =
-            "[" ++ tail (foldl' (\string e -> string ++ "," ++ show e) "" container) ++ "]"
-
--- Tensor is a functor
-instance Functor Tensor where
-
-    {-# INLINE fmap #-}
-    fmap f x = case x of
-        -- Mapping scalar simply maps its value
-        Scalar v                -> Scalar $ f v
-        -- Mapping complex tensor does mapping element by element
-        SimpleFinite index ts   -> SimpleFinite index (f <$> ts)
-        FiniteTensor index ts   -> FiniteTensor index $ fmap (fmap f) ts
-        InfiniteTensor index ts -> InfiniteTensor index $ fmap (fmap f) ts
-        -- Mapping errors changes nothing
-        Err msg                 -> Err msg
+                _                        -> "["  ++ tail (Boxed.foldl' (\string e -> string ++ "," ++ show e) "" ts) ++ "]"
 
 -- Tensors can be compared lexigographically
 -- Allowes to put tensors in typical ordered containers
 instance (
-    Ord a
+    Ord a, Unboxed.Unbox a
     ) => Ord (Tensor a) where
 
     {-# INLINE (<=) #-}
-    -- Error is smaller by other tensors, so when printing ordered containers, all erorrs will be printed first
-    -- Two errors are compared by they messages lexigographically
-    Err msg1 <= Err msg2 = msg1 <= msg2
-    Err _ <= _ = True
-    _ <= Err _ = False
     -- Scalar is smaller than any complex tensor
     -- Two scalars are compared by they values
     Scalar x1 <= Scalar x2 = x1 <= x2
@@ -258,71 +163,47 @@     -- Complex tensors are compared lexigographically
     SimpleFinite _ ts1 <= SimpleFinite _ ts2     = ts1 <= ts2
     FiniteTensor _ ts1 <= FiniteTensor _ ts2     = ts1 <= ts2
-    InfiniteTensor _ ts1 <= InfiniteTensor _ ts2 = ts1 <= ts2
     FiniteTensor _ _ <= SimpleFinite _ _         = False
     SimpleFinite _ _ <= FiniteTensor _ _         = True
-    InfiniteTensor _ _ <= FiniteTensor _ _       = False
-    FiniteTensor _ _ <= InfiniteTensor _ _       = True
-    InfiniteTensor _ _ <= SimpleFinite _ _       = False
-    SimpleFinite _ _ <= InfiniteTensor _ _       = True
 
 {-| Merge FiniteTensor of Scalars to SimpleFinite tensor for performance improvement -}
-{-# INLINE mergeScalars #-}
-mergeScalars :: Tensor a -> Tensor a
-mergeScalars x = case x of
+{-# INLINE _mergeScalars #-}
+_mergeScalars :: Unboxed.Unbox a => Tensor a -> Tensor a
+_mergeScalars x = case x of
     (FiniteTensor index1 ts1) -> case ts1 Boxed.! 0 of
-        Scalar _ -> SimpleFinite index1 (scalarVal <$> ts1)
-        _        -> FiniteTensor index1 $ mergeScalars <$> ts1
+        Scalar _ -> SimpleFinite index1 $ Unboxed.generate (Boxed.length ts1) (\i -> scalarVal (ts1 Boxed.! i))
+        _        -> FiniteTensor index1 $ _mergeScalars <$> ts1
     _ -> x
 
 {-| Apply a tensor operator (here denoted by (+) ) elem by elem, trying to connect as many common indices as possible -}
 {-# INLINE _elemByElem' #-}
-_elemByElem' :: Num a 
+_elemByElem' :: (Num a, Unboxed.Unbox a, NFData a)
              => Tensor a                            -- ^ First argument of operator
              -> Tensor a                            -- ^ Second argument of operator
-             -> (a -> a -> a)                       -- ^ Operator on tensor elements if indices are different
+             -> (a -> a -> a)                       -- ^ Function on tensor elements if indices are different
              -> (Tensor a -> Tensor a -> Tensor a)  -- ^ Tensor operator called if indices are the same
              -> Tensor a                            -- ^ Result tensor
 
 -- @Scalar x + Scalar y = Scalar x + y@
 _elemByElem' (Scalar x1) (Scalar x2) f _ = Scalar $ f x1 x2
 -- @Scalar x + Tensor t[i] = Tensor r[i] | r[i] = x + t[i]@
-_elemByElem' (Scalar x) t f _ = (x `f`) <$> t
+_elemByElem' (Scalar x) t f _ = (x `f`) `Multilinear.map` t
 -- @Tensor t[i] + Scalar x = Tensor r[i] | r[i] = t[i] + x@
-_elemByElem' t (Scalar x) f _ = (`f` x) <$> t
-
--- Two finite tensors case
-_elemByElem' t1@(FiniteTensor index1 v1) t2@(FiniteTensor index2 v2) f op
-    | Index.indexName index1 == Index.indexName index2 = op t1 t2
-    | Index.indexName index1 `Data.List.elem` indicesNames t2 =
-        FiniteTensor index2 $ (\x -> _elemByElem' t1 x f op) <$> v2
-    | otherwise = FiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
-
--- Two infinite tensors case
-_elemByElem' t1@(InfiniteTensor index1 v1) t2@(InfiniteTensor index2 v2) f op
-    | Index.indexName index1 == Index.indexName index2 = op t1 t2
-    | Index.indexName index1 `Data.List.elem` indicesNames t2 =
-        InfiniteTensor index2 $ (\x -> _elemByElem' t1 x f op) <$> v2
-    | otherwise = InfiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
+_elemByElem' t (Scalar x) f _ = (`f` x) `Multilinear.map` t
 
 -- Two simple tensors case
 _elemByElem' t1@(SimpleFinite index1 v1) t2@(SimpleFinite index2 _) f op
     | Index.indexName index1 == Index.indexName index2 = op t1 t2
-    | otherwise = FiniteTensor index1 $ (\x -> f x <$> t2) <$> v1
-
--- Finite and infinite tensor case
-_elemByElem' t1@(FiniteTensor index1 v1) t2@(InfiniteTensor index2 v2) f op
-    | Index.indexName index1 == Index.indexName index2 = op t1 t2
-    | Index.indexName index1 `Data.List.elem` indicesNames t2 =
-        InfiniteTensor index2 $ (\x -> _elemByElem' t1 x f op) <$> v2
-    | otherwise = FiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
+    | otherwise = FiniteTensor index1 $ 
+        Boxed.generate (Unboxed.length v1) 
+            (\i -> (\x -> f x `Multilinear.map` t2) (v1 Unboxed.! i))
 
--- Infinite and finite tensor case
-_elemByElem' t1@(InfiniteTensor index1 v1) t2@(FiniteTensor index2 v2) f op
+-- Two finite tensors case
+_elemByElem' t1@(FiniteTensor index1 v1) t2@(FiniteTensor index2 v2) f op
     | Index.indexName index1 == Index.indexName index2 = op t1 t2
     | Index.indexName index1 `Data.List.elem` indicesNames t2 =
         FiniteTensor index2 $ (\x -> _elemByElem' t1 x f op) <$> v2
-    | otherwise = InfiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
+    | otherwise = FiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
 
 -- Simple and finite tensor case
 _elemByElem' t1@(SimpleFinite index1 _) t2@(FiniteTensor index2 v2) f op
@@ -334,23 +215,9 @@     | Index.indexName index1 == Index.indexName index2 = op t1 t2
     | otherwise = FiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
 
--- Simple and infinite tensor case
-_elemByElem' t1@(SimpleFinite index1 _) t2@(InfiniteTensor index2 v2) f op
-    | Index.indexName index1 == Index.indexName index2 = op t1 t2
-    | otherwise = InfiniteTensor index2 $ (\x -> _elemByElem' t1 x f op) <$> v2
-
--- Infinite and simple tensor case
-_elemByElem' t1@(InfiniteTensor index1 v1) t2@(SimpleFinite index2 _) f op
-    | Index.indexName index1 == Index.indexName index2 = op t1 t2
-    | otherwise = InfiniteTensor index1 $ (\x -> _elemByElem' x t2 f op) <$> v1
-
--- Appying operator to error tensor simply pushes this error further
-_elemByElem' (Err msg) _ _ _ = Err msg
-_elemByElem' _ (Err msg) _ _ = Err msg
-
-{-| Apply a tensor operator elem by elem and merge scalars to simple tensor at the and -}
+{-| Apply a tensor operator elem by elem -}
 {-# INLINE _elemByElem #-}
-_elemByElem :: Num a 
+_elemByElem :: (Num a, Unboxed.Unbox a, NFData a)
             => Tensor a                             -- ^ First argument of operator
             -> Tensor a                             -- ^ Second argument of operator
             -> (a -> a -> a)                        -- ^ Operator on tensor elements if indices are different
@@ -360,11 +227,11 @@     let commonIndices = filter (`Data.List.elem` indicesNames t2) $ indicesNames t1
         t1' = foldl' (|>>>) t1 commonIndices
         t2' = foldl' (|>>>) t2 commonIndices
-    in mergeScalars $ _elemByElem' t1' t2' f op
+    in t1' `deepseq` t2' `deepseq` _mergeScalars $ _elemByElem' t1' t2' f op
 
 -- Zipping two tensors with a combinator, assuming they have the same indices
 {-# INLINE zipT #-}
-zipT :: Num a
+zipT :: (Num a, Unboxed.Unbox a, NFData a)
       => (Tensor a -> Tensor a -> Tensor a)   -- ^ Two tensors combinator
       -> (Tensor a -> a -> Tensor a)          -- ^ Tensor and scalar combinator
       -> (a -> Tensor a -> Tensor a)          -- ^ Scalar and tensor combinator
@@ -375,50 +242,36 @@ 
 -- Two simple tensors case
 zipT _ _ _ f (SimpleFinite index1 v1) (SimpleFinite index2 v2) = 
-    if index1 == index2 then SimpleFinite index1 $ Boxed.zipWith f v1 v2 else Err incompatibleTypes
+    if index1 == index2 then 
+        SimpleFinite index1 $ Unboxed.zipWith f v1 v2 
+    else error incompatibleTypes
 
 --Two finite tensors case
-zipT f _ _ _ (FiniteTensor index1 v1) (FiniteTensor index2 v2)     = 
-    if index1 == index2 then FiniteTensor index1 $ Boxed.zipWith f v1 v2 else Err incompatibleTypes
-
--- Two infinte tensors case
-zipT f _ _ _ (InfiniteTensor index1 v1) (InfiniteTensor index2 v2) = 
-    if index1 == index2 then InfiniteTensor index1 $ Data.List.zipWith f v1 v2 else Err incompatibleTypes
-
--- Infinite and finite tensor case
-zipT f _ _ _ (InfiniteTensor _ v1) (FiniteTensor index2 v2)   = 
-    FiniteTensor index2 $ Boxed.zipWith f (Boxed.fromList $ take (Boxed.length v2) v1) v2
-
--- Finite and infinite tensor case
-zipT f _ _ _ (FiniteTensor index1 v1) (InfiniteTensor _ v2)   = 
-    FiniteTensor index1 $ Boxed.zipWith f v1 (Boxed.fromList $ take (Boxed.length v1) v2)
+zipT f _ _ _ (FiniteTensor index1 v1) (FiniteTensor index2 v2) = 
+    if index1 == index2 then 
+        FiniteTensor index1 $ Boxed.zipWith f v1 v2 
+    else error incompatibleTypes
 
 -- Finite and simple tensor case
-zipT _ f _ _ (FiniteTensor index1 v1) (SimpleFinite index2 v2)     = 
-    if index1 == index2 then FiniteTensor index1 $ Boxed.zipWith f v1 v2 else Err incompatibleTypes
+zipT _ f _ _ (FiniteTensor index1 v1) (SimpleFinite index2 v2) = 
+    if index1 == index2 then 
+        FiniteTensor index1 $ 
+            Boxed.generate (Boxed.length v1) (\i -> f (v1 Boxed.! i) (v2 Unboxed.! i)) 
+    else error incompatibleTypes
 
 -- Simple and finite tensor case
-zipT _ _ f _ (SimpleFinite index1 v1) (FiniteTensor index2 v2)     = 
-    if index1 == index2 then FiniteTensor index1 $ Boxed.zipWith f v1 v2 else Err incompatibleTypes
-
--- Infinite and simple tensor case
-zipT _ f _ _ (InfiniteTensor _ v1) (SimpleFinite index2 v2)     = 
-    FiniteTensor index2 $ Boxed.zipWith f (Boxed.fromList $ take (Boxed.length v2) v1) v2
-
--- Simple and infinite tensor case
-zipT _ _ f _ (SimpleFinite index1 v1) (InfiniteTensor _ v2)     = 
-    FiniteTensor index1 $ Boxed.zipWith f v1 (Boxed.fromList $ take (Boxed.length v1) v2)
-
--- Zipping error tensor simply pushes this erorr further
-zipT _ _ _ _ (Err msg) _ = Err msg
-zipT _ _ _ _ _ (Err msg) = Err msg
+zipT _ _ f _ (SimpleFinite index1 v1) (FiniteTensor index2 v2) = 
+    if index1 == index2 then 
+        FiniteTensor index1 $ 
+            Boxed.generate (Unboxed.length v1) (\i -> f (v1 Unboxed.! i) (v2 Boxed.! i)) 
+    else error incompatibleTypes
 
 -- Zipping something with scalar is impossible
-zipT _ _ _ _ _ _ = Err scalarIndices
+zipT _ _ _ _ _ _ = error scalarIndices
 
 -- dot product of two tensors
 {-# INLINE dot #-}
-dot :: Num a
+dot :: (Num a, Unboxed.Unbox a, NFData a)
       => Tensor a  -- ^ First dot product argument
       -> Tensor a  -- ^ Second dot product argument
       -> Tensor a  -- ^ Resulting dot product
@@ -426,148 +279,30 @@ -- Two simple tensors product
 dot (SimpleFinite i1@(Finite.Covariant count1 _) ts1') (SimpleFinite i2@(Finite.Contravariant count2 _) ts2')
     | count1 == count2 = 
-        Scalar $ Boxed.sum $ Boxed.zipWith (*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (SimpleFinite i1@(Finite.Contravariant count1 _) ts1') (SimpleFinite i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = 
-        SimpleFinite i1 $ Boxed.zipWith (*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (SimpleFinite i1@(Finite.Covariant count1 _) ts1') (SimpleFinite i2@(Finite.Covariant count2 _) ts2')
-    | count1 == count2 = 
-        SimpleFinite i1 $ Boxed.zipWith (*) ts1' ts2'
+        Scalar $ Unboxed.sum $ Unboxed.zipWith (*) ts1' ts2'
     | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
 
 -- Two finite tensors product
 dot (FiniteTensor i1@(Finite.Covariant count1 _) ts1') (FiniteTensor i2@(Finite.Contravariant count2 _) ts2')
     | count1 == count2 = Boxed.sum $ Boxed.zipWith (*) ts1' ts2'
     | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (FiniteTensor i1@(Finite.Contravariant count1 _) ts1') (FiniteTensor i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = FiniteTensor i1 $ Boxed.zipWith (*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (FiniteTensor i1@(Finite.Covariant count1 _) ts1') (FiniteTensor i2@(Finite.Covariant count2 _) ts2')
-    | count1 == count2 = FiniteTensor i1 $ Boxed.zipWith (*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
 
-
--- Simple tensor and finite tensor product
-dot (SimpleFinite i1@(Finite.Covariant count1 _) ts1') (FiniteTensor i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = Boxed.sum $ Boxed.zipWith (*.) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (SimpleFinite i1@(Finite.Contravariant count1 _) ts1') (FiniteTensor i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = FiniteTensor i1 $ Boxed.zipWith (*.) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (SimpleFinite i1@(Finite.Covariant count1 _) ts1') (FiniteTensor i2@(Finite.Covariant count2 _) ts2')
-    | count1 == count2 = FiniteTensor i1 $ Boxed.zipWith (*.) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-
--- Finite tensor and simple tensor product
-dot (FiniteTensor i1@(Finite.Covariant count1 _) ts1') (SimpleFinite i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = Boxed.sum $ Boxed.zipWith (.*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (FiniteTensor i1@(Finite.Contravariant count1 _) ts1') (SimpleFinite i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = FiniteTensor i1 $ Boxed.zipWith (.*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-dot (FiniteTensor i1@(Finite.Covariant count1 _) ts1') (SimpleFinite i2@(Finite.Covariant count2 _) ts2')
-    | count1 == count2 = FiniteTensor i1 $ Boxed.zipWith (.*) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-
--- Simple tensor and infinite tensor product
-dot (SimpleFinite (Finite.Covariant count1 _) ts1') (InfiniteTensor (Infinite.Contravariant _) ts2') = 
-    Boxed.sum $ Boxed.zipWith (*.) ts1' (Boxed.fromList $ take count1 ts2')
-dot (SimpleFinite (Finite.Contravariant count1 _) ts1') (InfiniteTensor i2@(Infinite.Contravariant _) ts2') = 
-    InfiniteTensor i2 $ Boxed.toList $ Boxed.zipWith (*.) ts1' (Boxed.fromList $ take count1 ts2')
-dot (SimpleFinite (Finite.Covariant count1 _) ts1') (InfiniteTensor i2@(Infinite.Covariant _) ts2') = 
-    InfiniteTensor i2 $ Boxed.toList $ Boxed.zipWith (*.) ts1' (Boxed.fromList $ take count1 ts2')
-
--- Infinite tensor and simple tensor product
-dot (InfiniteTensor (Infinite.Covariant _) ts1') (SimpleFinite (Finite.Contravariant count2 _) ts2') = 
-    Boxed.sum $ Boxed.zipWith (.*) (Boxed.fromList $ take count2 ts1') ts2'
-dot (InfiniteTensor i1@(Infinite.Contravariant _) ts1') (SimpleFinite (Finite.Contravariant count2 _) ts2') = 
-    InfiniteTensor i1 $ Boxed.toList $ Boxed.zipWith (.*) (Boxed.fromList $ take count2 ts1') ts2'
-dot (InfiniteTensor i1@(Infinite.Covariant _) ts1') (SimpleFinite (Finite.Covariant count2 _) ts2') = 
-    InfiniteTensor i1 $ Boxed.toList $ Boxed.zipWith (.*) (Boxed.fromList $ take count2 ts1') ts2'
-
--- Finite tensor and infinite tensor product
-dot (FiniteTensor (Finite.Covariant count1 _) ts1') (InfiniteTensor (Infinite.Contravariant _) ts2') = 
-    Boxed.sum $ Boxed.zipWith (*) ts1' (Boxed.fromList $ take count1 ts2')
-dot (FiniteTensor (Finite.Contravariant count1 _) ts1') (InfiniteTensor i2@(Infinite.Contravariant _) ts2') = 
-    InfiniteTensor i2 $ Boxed.toList $ Boxed.zipWith (*) ts1' (Boxed.fromList $ take count1 ts2')
-dot (FiniteTensor (Finite.Covariant count1 _) ts1') (InfiniteTensor i2@(Infinite.Covariant _) ts2') = 
-    InfiniteTensor i2 $ Boxed.toList $ Boxed.zipWith (*) ts1' (Boxed.fromList $ take count1 ts2')
-
--- Infinite tensor and finite tensor product
-dot (InfiniteTensor (Infinite.Covariant _) ts1') (FiniteTensor (Finite.Contravariant count2 _) ts2') = 
-    Boxed.sum $ Boxed.zipWith (*) (Boxed.fromList $ take count2 ts1') ts2'
-dot (InfiniteTensor i1@(Infinite.Contravariant _) ts1') (FiniteTensor (Finite.Contravariant count2 _) ts2') = 
-    InfiniteTensor i1 $ Boxed.toList $ Boxed.zipWith (*) (Boxed.fromList $ take count2 ts1') ts2'
-dot (InfiniteTensor i1@(Infinite.Covariant _) ts1') (FiniteTensor (Finite.Covariant count2 _) ts2') = 
-    InfiniteTensor i1 $ Boxed.toList $ Boxed.zipWith (*) (Boxed.fromList $ take count2 ts1') ts2'
-
--- In other cases cannot happen!
+--  Other cases cannot happen!
 dot t1' t2' = contractionErr (tensorIndex t1') (tensorIndex t2')
 
--- bit dot product of two tensors
-{-# INLINE bitDot #-}
-bitDot :: (
-    Num a, Bits a
-    ) => Tensor a                             -- ^ First dot product argument
-      -> Tensor a                             -- ^ Second dot product argument
-      -> Tensor a                             -- ^ Resulting dot product
-
--- Two finite tensors product
-bitDot (FiniteTensor i1@(Finite.Covariant count1 _) ts1') (FiniteTensor i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = Data.Foldable.foldl' (.|.) 0 $ Boxed.zipWith (.&.) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-
--- Two simple tensors product
-bitDot (SimpleFinite i1@(Finite.Covariant count1 _) ts1') (SimpleFinite i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = 
-        let dotProduct v1 v2 =  Data.Foldable.foldl' (.|.) 0 $ Boxed.zipWith (.&.) v1 v2
-        in  Scalar $ dotProduct ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-
--- Simple tensor and finite tensor product
-bitDot (SimpleFinite i1@(Finite.Covariant count1 _) ts1') (FiniteTensor i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 =  Data.Foldable.foldl' (.|.) 0 $ Boxed.zipWith (\e t -> (e .&.) <$> t) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-
--- Finite tensor and simple tensor product
-bitDot (FiniteTensor i1@(Finite.Covariant count1 _) ts1') (SimpleFinite i2@(Finite.Contravariant count2 _) ts2')
-    | count1 == count2 = Data.Foldable.foldl' (.|.) 0 $ Boxed.zipWith (\t e -> (.&. e) <$> t) ts1' ts2'
-    | otherwise = contractionErr (Index.toTIndex i1) (Index.toTIndex i2)
-
--- Simple tensor and infinite tensor product
-bitDot (SimpleFinite (Finite.Covariant count1 _) ts1') (InfiniteTensor (Infinite.Contravariant _) ts2') = 
-    Data.Foldable.foldl' (.|.) 0 $ Boxed.zipWith (\e t -> (e .&.) <$> t) ts1' (Boxed.fromList $ take count1 ts2')
-
--- Infinite tensor and simple tensor product
-bitDot (InfiniteTensor (Infinite.Covariant _) ts1') (SimpleFinite (Finite.Contravariant count2 _) ts2') = 
-    Data.Foldable.foldl' (.|.) 0 $ Boxed.zipWith (\t e -> (.&. e) <$> t) (Boxed.fromList $ take count2 ts1') ts2'
-
--- Finite tensor and infinite tensor product
-bitDot (FiniteTensor (Finite.Covariant count1 _) ts1') (InfiniteTensor (Infinite.Contravariant _) ts2') = 
-    Boxed.sum $ Boxed.zipWith (*) ts1' (Boxed.fromList $ take count1 ts2')
-
--- Infinite tensor and finite tensor product
-bitDot (InfiniteTensor (Infinite.Covariant _) ts1') (FiniteTensor (Finite.Contravariant count2 _) ts2') = 
-    Boxed.sum $ Boxed.zipWith (*) (Boxed.fromList $ take count2 ts1') ts2'
-
--- In other cases cannot happen!
-bitDot t1' t2' = contractionErr (tensorIndex t1') (tensorIndex t2')
-
 -- contraction error
-{-# INLINE contractionErr #-}
+--{-# INLINE contractionErr #-}
 contractionErr :: Index.TIndex   -- ^ Index of first dot product parameter
                -> Index.TIndex   -- ^ Index of second dot product parameter
                -> Tensor a       -- ^ Erorr message
 
-contractionErr i1' i2' = Err $
+contractionErr i1' i2' = error $
     "Tensor product: " ++ incompatibleTypes ++
     " - index1 is " ++ show i1' ++
     " and index2 is " ++ show i2'
 
 -- Tensors can be added, subtracted and multiplicated
-instance Num a => Num (Tensor a) where
+instance (Unboxed.Unbox a, Num a, NFData a) => Num (Tensor a) where
 
     -- Adding - element by element
     {-# INLINE (+) #-}
@@ -584,101 +319,28 @@ 
     -- Absolute value - element by element
     {-# INLINE abs #-}
-    abs t = abs <$> t
+    abs t = abs `Multilinear.map` t
 
     -- Signum operation - element by element
     {-# INLINE signum #-}
-    signum t = signum <$> t
+    signum t = signum `Multilinear.map` t
 
     -- Simple integer can be conveted to Scalar
     {-# INLINE fromInteger #-}
     fromInteger x = Scalar $ fromInteger x
 
--- Bit operations on tensors
-instance (
-    Num a, Bits a
-    ) => Bits (Tensor a) where
-
-    -- Bit sum - elem by elem
-    {-# INLINE (.|.) #-}
-    t1 .|. t2 = _elemByElem t1 t2 (.|.) $ zipT (.|.) (\t e -> (.|. e) <$> t) (\e t -> (e .|.) <$> t) (.|.)
-
-    -- Bit tensor product
-    -- Summation and multiplication are replaced by its bit equivalents
-    -- Two scalars are multiplicated by their values
-    {-# INLINE (.&.) #-}
-    t1 .&. t2 = _elemByElem t1 t2 (.&.) bitDot
-
-    -- Bit exclusive sum (XOR) - elem by elem
-    {-# INLINE xor #-}
-    t1 `xor` t2 = _elemByElem t1 t2 xor $ zipT xor (\t e -> (`xor` e) <$> t) (\e t -> (e `xor`) <$> t) xor
-
-    -- Bit complement
-    {-# INLINE complement #-}
-    complement = Multilinear.map complement
-
-    -- Bit shift of all elements
-    {-# INLINE shift #-}
-    shift t n = Multilinear.map (`shift` n) t
-
-    -- Bit rotating of all elements
-    {-# INLINE rotate #-}
-    rotate t n = Multilinear.map (`rotate` n) t
-
-    -- Returns number of bits of elements of tensor, -1 for elements of undefined size
-    {-# INLINE bitSize #-}
-    bitSize (Scalar x)          = fromMaybe (-1) $ bitSizeMaybe x
-    bitSize (Err _)             = -1
-    bitSize t =
-        if isEmptyTensor t
-        then (-1)
-        else fromMaybe (-1) $ bitSizeMaybe $ firstElem t
-
-    -- Returns number of bits of elements of tensor
-    {-# INLINE bitSizeMaybe #-}
-    bitSizeMaybe (Scalar x)          = bitSizeMaybe x
-    bitSizeMaybe (Err _)             = Nothing
-    bitSizeMaybe t =
-        if isEmptyTensor t
-        then Nothing
-        else bitSizeMaybe $ firstElem t
-
-    -- Returns true if tensors element are signed
-    {-# INLINE isSigned #-}
-    isSigned (Scalar x)          = isSigned x
-    isSigned (Err _)             = False
-    isSigned t =
-        not (isEmptyTensor t) &&
-        isSigned (firstElem t)
-
-    -- bit i is a scalar value with the ith bit set and all other bits clear.
-    {-# INLINE bit #-}
-    bit i = Scalar (bit i)
-
-    -- Test bit - shoud retur True, if bit n if equal to 1.
-    -- Tensors are entities with many elements, so this function always returns False.
-    -- Do not use it, it is implemented only for legacy purposes.
-    {-# INLINE testBit #-}
-    testBit _ _ = False
-
-    -- Return the number of set bits in the argument. This number is known as the population count or the Hamming weight.
-    {-# INLINE popCount #-}
-    popCount = popCountDefault
-
 -- Tensors can be divided by each other
-instance Fractional a => Fractional (Tensor a) where
+instance (Unboxed.Unbox a, Fractional a, NFData a) => Fractional (Tensor a) where
 
     {-# INLINE (/) #-}
     -- Scalar division return result of division of its values
     Scalar x1 / Scalar x2 = Scalar $ x1 / x2
     -- Tensor and scalar are divided value by value
-    Scalar x1 / t2 = (x1 /) <$> t2
-    t1 / Scalar x2 = (/ x2) <$> t1
-    Err msg / _ = Err msg
-    _ / Err msg = Err msg
+    Scalar x1 / t2 = (x1 /) `Multilinear.map` t2
+    t1 / Scalar x2 = (/ x2) `Multilinear.map` t1
     -- Two complex tensors cannot be (for now) simply divided
     -- // TODO - tensor division and inversion
-    _ / _ = Err "TODO"
+    _ / _ = error "TODO"
 
     -- A scalar can be generated from rational number
     {-# INLINE fromRational #-}
@@ -687,7 +349,7 @@ -- Real-number functions on tensors.
 -- Function of tensor is tensor of function of its elements
 -- E.g. exp [1,2,3,4] = [exp 1, exp2, exp3, exp4]
-instance Floating a => Floating (Tensor a) where
+instance (Unboxed.Unbox a, Floating a, NFData a) => Floating (Tensor a) where
 
     {-| PI number -}
     {-# INLINE pi #-}
@@ -695,78 +357,78 @@ 
     {-| Exponential function. (exp t)[i] = exp( t[i] ) -}
     {-# INLINE exp #-}
-    exp t = exp <$> t
+    exp t = exp `Multilinear.map` t
 
     {-| Natural logarithm. (log t)[i] = log( t[i] ) -}
     {-# INLINE log #-}
-    log t = log <$> t
+    log t = log `Multilinear.map` t
 
     {-| Sinus. (sin t)[i] = sin( t[i] ) -}
     {-# INLINE sin #-}
-    sin t = sin <$> t
+    sin t = sin `Multilinear.map` t
 
     {-| Cosinus. (cos t)[i] = cos( t[i] ) -}
     {-# INLINE cos #-}
-    cos t = cos <$> t
+    cos t = cos `Multilinear.map` t
 
     {-| Inverse sinus. (asin t)[i] = asin( t[i] ) -}
     {-# INLINE asin #-}
-    asin t = asin <$> t
+    asin t = asin `Multilinear.map` t
 
     {-| Inverse cosinus. (acos t)[i] = acos( t[i] ) -}
     {-# INLINE acos #-}
-    acos t = acos <$> t
+    acos t = acos `Multilinear.map` t
 
     {-| Inverse tangent. (atan t)[i] = atan( t[i] ) -}
     {-# INLINE atan #-}
-    atan t = atan <$> t
+    atan t = atan `Multilinear.map` t
 
     {-| Hyperbolic sinus. (sinh t)[i] = sinh( t[i] ) -}
     {-# INLINE sinh #-}
-    sinh t = sinh <$> t
+    sinh t = sinh `Multilinear.map` t
 
     {-| Hyperbolic cosinus. (cosh t)[i] = cosh( t[i] ) -}
     {-# INLINE cosh #-}
-    cosh t = cosh <$> t
+    cosh t = cosh `Multilinear.map` t
 
     {-| Inverse hyperbolic sinus. (asinh t)[i] = asinh( t[i] ) -}
     {-# INLINE asinh #-}
-    asinh t = acosh <$> t
+    asinh t = acosh `Multilinear.map` t
 
     {-| Inverse hyperbolic cosinus. (acosh t)[i] = acosh (t[i] ) -}
     {-# INLINE acosh #-}
-    acosh t = acosh <$> t
+    acosh t = acosh `Multilinear.map` t
 
     {-| Inverse hyperbolic tangent. (atanh t)[i] = atanh( t[i] ) -}
     {-# INLINE atanh #-}
-    atanh t = atanh <$> t
+    atanh t = atanh `Multilinear.map` t
 
 -- Multilinear operations
-instance Num a => Multilinear Tensor a where
+instance (Unboxed.Unbox a, Num a, NFData a) => Multilinear Tensor a where
 
     -- Add scalar right
     {-# INLINE (.+) #-}
-    t .+ x = (+x) <$> t
+    t .+ x = (+x) `Multilinear.map` t
 
     -- Subtract scalar right
     {-# INLINE (.-) #-}
-    t .- x = (\p -> p - x) <$> t
+    t .- x = (\p -> p - x) `Multilinear.map` t
 
     -- Multiplicate by scalar right
     {-# INLINE (.*) #-}
-    t .* x = (*x) <$> t
+    t .* x = (*x) `Multilinear.map` t
 
     -- Add scalar left
     {-# INLINE (+.) #-}
-    x +. t = (x+) <$> t
+    x +. t = (x+) `Multilinear.map` t
 
     -- Subtract scalar left
     {-# INLINE (-.) #-}
-    x -. t = (x-) <$> t
+    x -. t = (x-) `Multilinear.map` t
 
     -- Multiplicate by scalar left
     {-# INLINE (*.) #-}
-    x *. t = (x*) <$> t
+    x *. t = (x*) `Multilinear.map` t
 
     -- Two tensors sum
     {-# INLINE (.+.) #-}
@@ -785,9 +447,7 @@     indices x = case x of
         Scalar _            -> []
         FiniteTensor i ts   -> Index.toTIndex i : indices (head $ toList ts)
-        InfiniteTensor i ts -> Index.toTIndex i : indices (head ts)
         SimpleFinite i _    -> [Index.toTIndex i]
-        Err _               -> []
 
     -- Get tensor order [ (contravariant,covariant)-type ]
     {-# INLINE order #-}
@@ -797,7 +457,6 @@             Finite.Contravariant _ _ -> (1,0)
             Finite.Covariant _ _     -> (0,1)
             Finite.Indifferent _ _   -> (0,0)
-        Err _ -> (-1,-1)
         _ -> let (cnvr, covr) = order $ firstTensor x
              in case tensorIndex x of
                 Index.Contravariant _ _ -> (cnvr+1,covr)
@@ -816,8 +475,6 @@             if Index.indexName index == iname
             then Finite.indexSize index
             else size (firstTensor t) iname
-        InfiniteTensor _ _   -> error infiniteIndex
-        Err msg              -> error msg
 
     -- Rename tensor indices
     {-# INLINE ($|) #-}
@@ -827,9 +484,6 @@     SimpleFinite (Finite.Covariant isize _) ts $| (_, d:_) = SimpleFinite (Finite.Covariant isize [d]) ts
     FiniteTensor (Finite.Contravariant isize _) ts $| (u:us, ds) = FiniteTensor (Finite.Contravariant isize [u]) $ ($| (us,ds)) <$> ts
     FiniteTensor (Finite.Covariant isize _) ts $| (us, d:ds) = FiniteTensor (Finite.Covariant isize [d]) $ ($| (us,ds)) <$> ts
-    InfiniteTensor (Infinite.Contravariant _) ts $| (u:us, ds) = InfiniteTensor (Infinite.Contravariant [u]) $ ($| (us,ds)) <$> ts
-    InfiniteTensor (Infinite.Covariant _) ts $| (us, d:ds) = InfiniteTensor (Infinite.Covariant [d]) $ ($| (us,ds)) <$> ts
-    Err msg $| _ = Err msg
     t $| _ = t
 
     -- Raise an index
@@ -840,16 +494,10 @@             FiniteTensor (Finite.Contravariant (Finite.indexSize index) n) $ (/\ n) <$> ts
         | otherwise =
             FiniteTensor index $ (/\ n) <$> ts
-    InfiniteTensor index ts /\ n
-        | Index.indexName index == n =
-            InfiniteTensor (Infinite.Contravariant n) $ (/\ n) <$> ts
-        | otherwise =
-            InfiniteTensor index $ (/\ n) <$> ts
     t1@(SimpleFinite index ts) /\ n
         | Index.indexName index == n =
             SimpleFinite (Finite.Contravariant (Finite.indexSize index) n) ts
         | otherwise = t1
-    Err msg /\ _ = Err msg
 
     -- Lower an index
     {-# INLINE (\/) #-}
@@ -859,16 +507,10 @@             FiniteTensor (Finite.Covariant (Finite.indexSize index) n) $ (\/ n) <$> ts
         | otherwise =
             FiniteTensor index $ (\/ n) <$> ts
-    InfiniteTensor index ts \/ n
-        | Index.indexName index == n =
-            InfiniteTensor (Infinite.Covariant n) $ (\/ n) <$> ts
-        | otherwise =
-            InfiniteTensor index $ (\/ n) <$> ts
     t1@(SimpleFinite index ts) \/ n
         | Index.indexName index == n =
             SimpleFinite (Finite.Covariant (Finite.indexSize index) n) ts
         | otherwise = t1
-    Err msg \/ _ = Err msg
 
     {-| Transpose a tensor (switch all indices types) -}
     {-# INLINE transpose #-}
@@ -881,13 +523,6 @@     transpose (FiniteTensor (Finite.Indifferent count name) ts) =
         FiniteTensor (Finite.Indifferent count name) (Multilinear.transpose <$> ts)
 
-    transpose (InfiniteTensor (Infinite.Covariant name) ts) =
-        InfiniteTensor (Infinite.Contravariant name) (Multilinear.transpose <$> ts)
-    transpose (InfiniteTensor (Infinite.Contravariant name) ts) =
-        InfiniteTensor (Infinite.Covariant name) (Multilinear.transpose <$> ts)
-    transpose (InfiniteTensor (Infinite.Indifferent name) ts) =
-        InfiniteTensor (Infinite.Indifferent name) (Multilinear.transpose <$> ts)
-
     transpose (SimpleFinite (Finite.Covariant count name) ts) =
         SimpleFinite (Finite.Contravariant count name) ts
     transpose (SimpleFinite (Finite.Contravariant count name) ts) =
@@ -895,13 +530,9 @@     transpose (SimpleFinite (Finite.Indifferent count name) ts) =
         SimpleFinite (Finite.Indifferent count name) ts
 
-    transpose (Err msg) = Err msg
 
     {-| Shift tensor index right -}
     {-| Moves given index one level deeper in recursion -}
-    {-# INLINE shiftRight #-}
-    -- Error tensor has no indices to shift
-    Err msg `shiftRight` _  = Err msg
     -- Scalar has no indices to shift
     Scalar x `shiftRight` _ = Scalar x
     -- Simple tensor has only one index which cannot be shifted
@@ -917,7 +548,8 @@             let index2 = tensorFiniteIndex (ts1 Boxed.! 0)
                 -- Elements to transpose
                 dane = if isSimple (ts1 Boxed.! 0)
-                       then (Scalar <$>) <$> (tensorScalars <$> ts1)
+                       then (\un -> Boxed.generate (Unboxed.length un) (\i -> Scalar $ un Unboxed.! i)) <$> 
+                            (tensorScalars <$> ts1)
                        else tensorsFinite <$> ts1
                 -- Convert to list
                 daneList = Boxed.toList <$> Boxed.toList dane
@@ -926,31 +558,21 @@                 -- then reconvert to vector again
                 transposed = Boxed.fromList <$> Boxed.fromList transposedList
             -- and reconstruct tensor with transposed elements
-            in  mergeScalars $ FiniteTensor index2 $ FiniteTensor index1 <$> transposed
-        | otherwise = t1
-
-    -- Infinite tensor is shifted by transposing nested lists
-    t1@(InfiniteTensor index1 ts1) `shiftRight` ind
-        -- We don't shift this index
-        | Data.List.length (indicesNames t1) > 1 && Index.indexName index1 /= ind =
-            InfiniteTensor index1 $ (|>> ind) <$> ts1
-        -- We found index to shift
-        | Data.List.length (indicesNames t1) > 1 && Index.indexName index1 == ind =
-                -- Next index
-            let index2 = tensorInfiniteIndex (head ts1)
-                -- Elements to transpose
-                dane = if isSimple (head ts1)
-                       then (Scalar <$>) <$> (Boxed.toList . tensorScalars <$> ts1)
-                       else tensorsInfinite <$> ts1
-                -- transpose tensor data (standard function available only for list)
-                transposed = Data.List.transpose dane
-            -- and reconstruct tensor with transposed elements
-            in  mergeScalars $ InfiniteTensor index2 $ InfiniteTensor index1 <$> transposed
+            in  _mergeScalars $ FiniteTensor index2 $ FiniteTensor index1 <$> transposed
+        -- there is only one index and therefore it cannot be shifted
         | otherwise = t1
-
+    
+    {-| Map function, as in Functor typeclass -}
+    {-# INLINE map #-}
+    map f x = case x of
+        -- Mapping scalar simply maps its value
+        Scalar v                -> Scalar $ f v
+        -- Mapping complex tensor does mapping element by element
+        SimpleFinite index ts   -> SimpleFinite index (f `Unboxed.map` ts)
+        FiniteTensor index ts   -> FiniteTensor index $ Multilinear.map f <$> ts
 
 {-| List allows for random access to tensor elements -}
-instance Num a => Accessible Tensor a where
+instance (Unboxed.Unbox a, Num a, NFData a) => Accessible Tensor a where
 
     {-| Accessing tensor elements -}
     {-# INLINE el #-}
@@ -989,42 +611,3 @@             then el (t1 ! snd (fromJust val)) (inds1,vals1)
             -- otherwise recursively access elements of all child tensors
             else FiniteTensor index1 $ (\t -> el t (inds,vals)) <$> v1
-
-    -- infinite tensor case
-    el t1@(InfiniteTensor index1 v1) (inds,vals) =
-            -- zip indices with their given values
-        let indvals = zip inds vals
-            -- find value for current index if given
-            val = Data.List.find (\(n,_) -> [n] == Index.indexName index1) indvals
-            -- and remove used index from indices list
-            indvals1 = Data.List.filter (\(n,_) -> [n] /= Index.indexName index1) indvals
-            -- indices unused so far
-            inds1 = Data.List.map fst indvals1
-            -- and its corresponding values
-            vals1 = Data.List.map snd indvals1
-            -- if value for current index was given
-        in  if isJust val
-            -- then get it from current tensor and recursively process other indices
-            then el (t1 ! snd (fromJust val)) (inds1,vals1)
-            -- otherwise recursively access elements of all child tensors
-            else InfiniteTensor index1 $ (\t -> el  t (inds,vals)) <$> v1
-
-    -- accessing elements of erorr tensor simply pushes this error further
-    el (Err msg) _ = Err msg
-
-    {-| Mapping with indices. -}
-    {-# INLINE iMap #-}
-    iMap f t = iMap' t zeroList
-        where
-        zeroList = 0:zeroList
-
-        iMap' (Scalar x) inds =
-            Scalar $ f inds x
-        iMap' (SimpleFinite index ts) inds =
-            SimpleFinite index $ Boxed.imap (\i e -> f (inds ++ [i]) e) ts
-        iMap' (FiniteTensor index ts) inds =
-            FiniteTensor index $ Boxed.imap (\i e -> iMap' e (inds ++ [i])) ts
-        iMap' (InfiniteTensor index  ts) inds =
-            InfiniteTensor index $ (\tind -> iMap' (fst tind) $ inds ++ [snd tind]) <$> zip ts [0..]
-        iMap' (Err msg) _  =
-            Err msg
src/Multilinear/Matrix.hs view
@@ -23,6 +23,7 @@ ) where
 
 import           Control.Monad.Primitive
+import qualified Data.Vector.Unboxed        as Unboxed
 import           Multilinear.Generic
 import qualified Multilinear.Tensor         as Tensor
 import           Statistics.Distribution
@@ -31,9 +32,9 @@ invalidIndices = "Indices and its sizes not compatible with structure of matrix!"
 
 {-| Generate matrix as function of its indices -}
-{-# INLINE fromIndices #-}
+
 fromIndices :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String               -- ^ Indices names (one character per index, first character: rows index, second character: columns index)
     -> Int                  -- ^ Number of matrix rows
     -> Int                  -- ^ Number of matrix columns
@@ -41,12 +42,12 @@     -> Tensor a             -- ^ Generated matrix
 
 fromIndices [u,d] us ds f = Tensor.fromIndices ([u],[us]) ([d],[ds]) $ \[ui] [di] -> f ui di
-fromIndices _ _ _ _ = Err invalidIndices
+fromIndices _ _ _ _ = error invalidIndices
 
 {-| Generate matrix with all components equal to @v@ -}
-{-# INLINE Multilinear.Matrix.const #-}
+
 const :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String    -- ^ Indices names (one character per index, first character: rows index, second character: columns index)
     -> Int       -- ^ Number of matrix rows
     -> Int       -- ^ Number of matrix columns
@@ -54,7 +55,7 @@     -> Tensor a  -- ^ Generated matrix
 
 const [u,d] us ds = Tensor.const ([u],[us]) ([d],[ds])
-const _ _ _ = \_ -> Err invalidIndices
+const _ _ _ = \_ -> error invalidIndices
 
 {-| Generate matrix with random real components with given probability distribution.
 The matrix is wrapped in the IO monad. -}
@@ -69,7 +70,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDouble #-}
+
 randomDouble :: (
     ContGen d
   ) => String              -- ^ Indices names (one character per index, first character: rows index, second character: columns index)
@@ -79,7 +80,7 @@     -> IO (Tensor Double)  -- ^ Generated matrix
 
 randomDouble [u,d] us ds = Tensor.randomDouble ([u],[us]) ([d],[ds])
-randomDouble _ _ _ = \_ -> return $ Err invalidIndices
+randomDouble _ _ _ = \_ -> return $ error invalidIndices
 
 {-| Generate matrix with random integer components with given probability distribution.
 The matrix is wrapped in the IO monad. -}
@@ -88,7 +89,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomInt #-}
+
 randomInt :: (
     DiscreteGen d
   ) => String           -- ^ Indices names (one character per index, first character: rows index, second character: columns index)
@@ -98,7 +99,7 @@     -> IO (Tensor Int)  -- ^ Generated matrix
 
 randomInt [u,d] us ds = Tensor.randomInt ([u],[us]) ([d],[ds])
-randomInt _ _ _ = \_ -> return $ Err invalidIndices
+randomInt _ _ _ = \_ -> return $ error invalidIndices
 
 {-| Generate matrix with random real components with given probability distribution and given seed.
 The matrix is wrapped in the a monad. -}
@@ -113,7 +114,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDoubleSeed #-}
+
 randomDoubleSeed :: (
     ContGen d, PrimMonad m
   ) => String              -- ^ Indices names (one character per index, first character: rows index, second character: columns index)
@@ -124,7 +125,7 @@     -> m (Tensor Double)   -- ^ Generated matrix
 
 randomDoubleSeed [u,d] us ds = Tensor.randomDoubleSeed ([u],[us]) ([d],[ds])
-randomDoubleSeed _ _ _ = \_ _ -> return $ Err invalidIndices
+randomDoubleSeed _ _ _ = \_ _ -> return $ error invalidIndices
 
 {-| Generate matrix with random integer components with given probability distribution. and given seed.
 The matrix is wrapped in a monad. -}
@@ -133,7 +134,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomIntSeed #-}
+
 randomIntSeed :: (
     DiscreteGen d, PrimMonad m
   ) => String              -- ^ Indices names (one character per index, first character: rows index, second character: columns index)
@@ -144,4 +145,4 @@     -> m (Tensor Int)      -- ^ Generated matrix
 
 randomIntSeed [u,d] us ds = Tensor.randomIntSeed ([u],[us]) ([d],[ds])
-randomIntSeed _ _ _ = \_ _ -> return $ Err invalidIndices
+randomIntSeed _ _ _ = \_ _ -> return $ error invalidIndices
src/Multilinear/NForm.hs view
@@ -26,6 +26,7 @@ ) where
 
 import           Control.Monad.Primitive
+import qualified Data.Vector.Unboxed      as Unboxed
 import           Multilinear.Generic
 import qualified Multilinear.Tensor       as Tensor
 import           Statistics.Distribution
@@ -37,9 +38,9 @@ invalidCrossProductIndices = "Indices and its sizes incompatible with cross product structure!"
 
 {-| Generate N-form as function of its indices -}
-{-# INLINE fromIndices #-}
+
 fromIndices :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String        -- ^ Indices names (one characted per index)
     -> [Int]         -- ^ Indices sizes
     -> ([Int] -> a)  -- ^ Generator function
@@ -48,9 +49,9 @@ fromIndices d ds f = Tensor.fromIndices ([],[]) (d,ds) $ \[] -> f
 
 {-| Generate N-form with all components equal to @v@ -}
-{-# INLINE Multilinear.NForm.const #-}
+
 const :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String    -- ^ Indices names (one characted per index)
     -> [Int]     -- ^ Indices sizes
     -> a         -- ^ N-form elements value
@@ -72,7 +73,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDouble #-}
+
 randomDouble :: (
     ContGen d
   ) => String              -- ^ Indices names (one character per index)
@@ -89,7 +90,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomInt #-}
+
 randomInt :: (
     DiscreteGen d
   ) => String              -- ^ Indices names (one character per index)
@@ -113,7 +114,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDoubleSeed #-}
+
 randomDoubleSeed :: (
     ContGen d, PrimMonad m
   ) => String            -- ^ Index name (one character)
@@ -131,7 +132,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomIntSeed #-}
+
 randomIntSeed :: (
     DiscreteGen d, PrimMonad m
   ) => String            -- ^ Index name (one character)
@@ -143,21 +144,21 @@ randomIntSeed d ds = Tensor.randomIntSeed ([],[]) (d,ds)
 
 {-| 2-form representing a dot product -}
-{-# INLINE dot #-}
+
 dot :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String    -- ^ Indices names (one characted per index)
     -> Int       -- ^ Size of tensor (dot product is a square tensor)
     -> Tensor a  -- ^ Generated dot product
 
 dot [i1,i2] size = fromIndices [i1,i2] [size,size] (\[i,j] -> if i == j then 1 else 0)
-dot _ _ = Err invalidIndices
+dot _ _ = error invalidIndices
 
 {-| Tensor representing a cross product (Levi - Civita symbol). It also allows to compute a determinant of square matrix - determinant of matrix @M@ is a equal to length of cross product of all columns of @M@ -}
 -- // TODO
-{-# INLINE cross #-}
+
 cross :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String    -- ^ Indices names (one characted per index)
     -> Int       -- ^ Size of tensor (dot product is a square tensor)
     -> Tensor a  -- ^ Generated dot product
@@ -165,4 +166,4 @@ cross [i,j,k] size =
   Tensor.fromIndices ([i],[size]) ([j,k],[size,size])
     (\[_] [_,_] -> 0)
-cross _ _ = Err invalidCrossProductIndices
+cross _ _ = error invalidCrossProductIndices
src/Multilinear/NVector.hs view
@@ -23,14 +23,15 @@ ) where
 
 import           Control.Monad.Primitive
+import qualified Data.Vector.Unboxed         as Unboxed
 import           Multilinear.Generic
 import           Multilinear.Tensor          as Tensor
 import           Statistics.Distribution
 
 {-| Generate n-vector as function of its indices -}
-{-# INLINE fromIndices #-}
+
 fromIndices :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String        -- ^ Indices names (one characted per index)
     -> [Int]         -- ^ Indices sizes
     -> ([Int] -> a)  -- ^ Generator function
@@ -39,9 +40,9 @@ fromIndices u us f = Tensor.fromIndices (u,us) ([],[]) $ \uis [] -> f uis
 
 {-| Generate n-vector with all components equal to @v@ -}
-{-# INLINE Multilinear.NForm.const #-}
+
 const :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String    -- ^ Indices names (one characted per index)
     -> [Int]     -- ^ Indices sizes
     -> a         -- ^ n-vector elements value
@@ -63,7 +64,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDouble #-}
+
 randomDouble :: (
     ContGen d
   ) => String              -- ^ Indices names (one character per index)
@@ -80,7 +81,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomInt #-}
+
 randomInt :: (
     DiscreteGen d
   ) => String              -- ^ Indices names (one character per index)
@@ -104,7 +105,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDoubleSeed #-}
+
 randomDoubleSeed :: (
     ContGen d, PrimMonad m
   ) => String            -- ^ Index name (one character)
@@ -122,7 +123,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomIntSeed #-}
+
 randomIntSeed :: (
     DiscreteGen d, PrimMonad m
   ) => String            -- ^ Index name (one character)
src/Multilinear/Tensor.hs view
@@ -25,6 +25,7 @@ 
 import           Control.Monad.Primitive
 import qualified Data.Vector                as Boxed
+import qualified Data.Vector.Unboxed        as Unboxed
 import           Multilinear.Generic
 import           Multilinear.Index.Finite   as Finite
 import           Statistics.Distribution
@@ -34,9 +35,9 @@ invalidIndices us ds = "Indices and its sizes incompatible, upper indices: " ++ show us ++", lower indices: " ++ show ds
 
 {-| Generate tensor as functions of its indices -}
-{-# INLINE fromIndices #-}
+
 fromIndices :: (
-    Num a
+    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] -> a)   -- ^ Generator function (f [u1,u2,...] [d1,d2,...] returns a tensor element at t [u1,u2,...] [d1,d2,...])
@@ -44,11 +45,11 @@ 
 -- If only one upper index is given, generate a SimpleFinite tensor with upper index
 fromIndices ([u],[s]) ([],[]) f = 
-  SimpleFinite (Contravariant s [u]) $ Boxed.generate s $ \x -> f [x] []
+  SimpleFinite (Contravariant s [u]) $ Unboxed.generate s $ \x -> f [x] []
 
 -- If only one lower index is given, generate a SimpleFinite tensor with lower index
 fromIndices ([],[]) ([d],[s]) f = 
-  SimpleFinite (Covariant s [d]) $ Boxed.generate s $ \x -> f [] [x]
+  SimpleFinite (Covariant s [d]) $ Unboxed.generate s $ \x -> f [] [x]
 
 -- If many indices are given, first generate upper indices recursively from indices list
 fromIndices (u:us,s:size) d f =
@@ -59,12 +60,12 @@     FiniteTensor (Covariant s [d]) $ Boxed.generate s (\x -> fromIndices u (ds,size) (\uss dss -> f uss (x:dss)) )
 
 -- If there are indices without size or sizes without names, throw an error
-fromIndices us ds _ = Err $ invalidIndices us ds
+fromIndices us ds _ = error $ invalidIndices us ds
 
 {-| Generate tensor composed of other tensors -}
-{-# INLINE generate #-}
+
 generate :: (
-    Num a
+    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,...])
@@ -82,12 +83,12 @@     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 _ = Err $ invalidIndices us ds
+generate us ds _ = error $ invalidIndices us ds
 
 {-| Generate tensor with all components equal to @v@ -}
-{-# INLINE Multilinear.Tensor.const #-}
+
 const :: (
-    Num a
+    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
       -> a              -- ^ Tensor elements value
@@ -95,11 +96,11 @@ 
 -- If only one upper index is given, generate a SimpleFinite tensor with upper index
 const ([u],[s]) ([],[]) v =
-  SimpleFinite (Contravariant s [u]) $ Boxed.replicate s v
+  SimpleFinite (Contravariant s [u]) $ Unboxed.replicate s v
 
 -- If only ine lower index is given, generate a SimpleFinite tensor with lower index
 const ([],[]) ([d],[s]) v =
-  SimpleFinite (Covariant s [d]) $ Boxed.replicate s v
+  SimpleFinite (Covariant s [d]) $ Unboxed.replicate s v
 
 -- If many indices are given, first generate upper indices recursively from indices list
 const (u:us,s:size) d v =
@@ -110,7 +111,7 @@     FiniteTensor (Covariant s [d]) $ Boxed.replicate (fromIntegral s) $ Multilinear.Tensor.const u (ds,size) v
 
 -- If there are indices without size or sizes without names, throw an error
-const us ds _ = Err $ invalidIndices us ds
+const us ds _ = error $ invalidIndices us ds
 
 {-| Generate tensor with random real components with given probability distribution.
 The tensor is wrapped in the IO monad. -}
@@ -126,7 +127,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDouble #-}
+
 randomDouble :: (
     ContGen d
   ) => (String,[Int])      -- ^ Upper indices names (one character per index) and its sizes
@@ -137,13 +138,15 @@ -- If only one upper index is given, generate a SimpleFinite tensor with upper index
 randomDouble ([u],[s]) ([],[]) distr = do
     gen <- MWC.createSystemRandom
-    component <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Contravariant s [u]) component
 
 -- If only one lower index is given, generate a SimpleFinite tensor with lower index
 randomDouble ([],[]) ([d],[s]) distr = do
     gen <- MWC.createSystemRandom
-    component <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Covariant s [d]) component
 
 -- If many indices are given, first generate upper indices recursively from indices list
@@ -157,7 +160,7 @@   return $ FiniteTensor (Covariant s [d]) tensors
 
 -- If there are indices without size or sizes without names, throw an error
-randomDouble us ds _ = return $ Err $ invalidIndices us ds
+randomDouble us ds _ = return $ error $ invalidIndices us ds
 
 {-| Generate tensor with random integer components with given probability distribution.
 The tensor is wrapped in the IO monad. -}
@@ -166,7 +169,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomInt #-}
+
 randomInt :: (
     DiscreteGen d
   ) => (String,[Int])    -- ^ Upper indices names (one character per index) and its sizes
@@ -177,13 +180,15 @@ -- If only one upper index is given, generate a SimpleFinite tensor with upper index
 randomInt ([u],[s]) ([],[]) distr = do
     gen <- MWC.createSystemRandom
-    component <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Contravariant s [u]) component
 
 -- If only one lower index is given, generate a SimpleFinite tensor with lower index
 randomInt ([],[]) ([d],[s]) distr = do
     gen <- MWC.createSystemRandom
-    component <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Covariant s [d]) component
 
 -- If many indices are given, first generate upper indices recursively from indices list
@@ -197,7 +202,7 @@   return $ FiniteTensor (Covariant s [d]) tensors
 
 -- If there are indices without size or sizes without names, throw an error
-randomInt us ds _ = return $ Err $ invalidIndices us ds
+randomInt us ds _ = return $ error $ invalidIndices us ds
 
 {-| Generate tensor with random real components with given probability distribution and given seed.
 The tensor is wrapped in a monad. -}
@@ -213,7 +218,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDoubleSeed #-}
+
 randomDoubleSeed :: (
     ContGen d, PrimMonad m
   ) => (String,[Int])    -- ^ Upper indices names (one character per index) and its sizes
@@ -225,13 +230,15 @@ -- If only one upper index is given, generate a SimpleFinite tensor with upper index
 randomDoubleSeed ([u],[s]) ([],[]) distr seed = do
     gen <- MWC.initialize (Boxed.singleton $ fromIntegral seed)
-    component <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Contravariant s [u]) component
 
 -- If only one lower index is given, generate a SimpleFinite tensor with lower index
 randomDoubleSeed ([],[]) ([d],[s]) distr seed = do
     gen <- MWC.initialize (Boxed.singleton $ fromIntegral seed)
-    component <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genContVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Covariant s [d]) component
 
 -- If many indices are given, first generate upper indices recursively from indices list
@@ -245,7 +252,7 @@   return $ FiniteTensor (Covariant s [d]) tensors
 
 -- If there are indices without size or sizes without names, throw an error
-randomDoubleSeed us ds _ _ = return $ Err $ invalidIndices us ds
+randomDoubleSeed us ds _ _ = return $ error $ invalidIndices us ds
 
 {-| Generate tensor with random integer components with given probability distribution and given seed.
 The tensor is wrapped in a monad. -}
@@ -254,7 +261,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomIntSeed #-}
+
 randomIntSeed :: (
     DiscreteGen d, PrimMonad m
   ) => (String,[Int])    -- ^ Index name (one character)
@@ -266,13 +273,15 @@ -- If only one upper index is given, generate a SimpleFinite tensor with upper index
 randomIntSeed ([u],[s]) ([],[]) distr seed = do
     gen <- MWC.initialize (Boxed.singleton $ fromIntegral seed)
-    component <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Contravariant s [u]) component
 
 -- If only one lower index is given, generate a SimpleFinite tensor with lower index
 randomIntSeed ([],[]) ([d],[s]) distr seed = do
     gen <- MWC.initialize (Boxed.singleton $ fromIntegral seed)
-    component <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    component' <- sequence $ Boxed.generate s $ \_ -> genDiscreteVar distr gen
+    let component = Unboxed.generate s $ \i -> component' Boxed.! i
     return $ SimpleFinite (Covariant s [d]) component
 
 -- If many indices are given, first generate upper indices recursively from indices list
@@ -286,4 +295,4 @@   return $ FiniteTensor (Covariant s [d]) tensors
 
 -- If there are indices without size or sizes without names, throw an error
-randomIntSeed us ds _ _ = return $ Err $ invalidIndices us ds
+randomIntSeed us ds _ _ = return $ error $ invalidIndices us ds
src/Multilinear/Vector.hs view
@@ -23,6 +23,7 @@ ) where
 
 import           Control.Monad.Primitive
+import qualified Data.Vector.Unboxed        as Unboxed
 import           Multilinear.Generic
 import           Multilinear.Tensor         as Tensor
 import           Statistics.Distribution
@@ -31,28 +32,28 @@ invalidIndices = "Indices and its sizes not compatible with structure of vector!"
 
 {-| Generate vector as function of indices -}
-{-# INLINE fromIndices #-}
+
 fromIndices :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String        -- ^ Index name (one character)
     -> Int           -- ^ Number of elements
     -> (Int -> a)    -- ^ Generator function - returns a vector component at index @i@
     -> Tensor a      -- ^ Generated vector
 
 fromIndices [i] s f = Tensor.fromIndices ([i],[s]) ([],[]) $ \[x] [] -> f x
-fromIndices _ _ _ = Err invalidIndices
+fromIndices _ _ _ = error invalidIndices
 
 {-| Generate vector with all components equal to some @v@ -}
-{-# INLINE Multilinear.Vector.const #-}
+
 const :: (
-    Num a
+    Num a, Unboxed.Unbox a
   ) => String      -- ^ Index name (one character)
     -> Int         -- ^ Number of elements
     -> a           -- ^ Value of each element
     -> Tensor a    -- ^ Generated vector
 
 const [i] s = Tensor.const ([i],[s]) ([],[])
-const _ _ = \_ -> Err invalidIndices
+const _ _ = \_ -> error invalidIndices
 
 {-| Generate vector with random real components with given probability distribution.
 The vector is wrapped in the IO monad. -}
@@ -67,7 +68,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDouble #-}
+
 randomDouble :: (
     ContGen d
   ) => String              -- ^ Index name (one character)
@@ -76,7 +77,7 @@     -> IO (Tensor Double)  -- ^ Generated vector
 
 randomDouble [i] s = Tensor.randomDouble ([i],[s]) ([],[])
-randomDouble _ _ = \_ -> return $ Err invalidIndices
+randomDouble _ _ = \_ -> return $ error invalidIndices
 
 {-| Generate vector with random integer components with given probability distribution.
 The vector is wrapped in the IO monad. -}
@@ -85,7 +86,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomInt #-}
+
 randomInt :: (
     DiscreteGen d
   ) => String           -- ^ Index name (one character)
@@ -94,7 +95,7 @@     -> IO (Tensor Int)  -- ^ Generated vector
 
 randomInt [i] s = Tensor.randomInt ([i],[s]) ([],[])
-randomInt _ _ = \_ -> return $ Err invalidIndices
+randomInt _ _ = \_ -> return $ error invalidIndices
 
 {-| Generate vector with random real components with given probability distribution and given seed.
 The vector is wrapped in a monad. -}
@@ -109,7 +110,7 @@ {-| - Uniform : "Statistics.Distribution.Uniform" -}
 {-| - F : "Statistics.Distribution.FDistribution" -}
 {-| - Laplace : "Statistics.Distribution.Laplace" -}
-{-# INLINE randomDoubleSeed #-}
+
 randomDoubleSeed :: (
     ContGen d, PrimMonad m
   ) => String             -- ^ Index name (one character)
@@ -119,7 +120,7 @@     -> m (Tensor Double)  -- ^ Generated vector
 
 randomDoubleSeed [i] s = Tensor.randomDoubleSeed ([i],[s]) ([],[])
-randomDoubleSeed _ _ = \_ _ -> return $ Err invalidIndices
+randomDoubleSeed _ _ = \_ _ -> return $ error invalidIndices
 
 {-| Generate vector with random integer components with given probability distribution and given seed.
 The vector is wrapped in a monad. -}
@@ -128,7 +129,7 @@ {-| - Poisson : "Statistics.Distribution.Poisson" -}
 {-| - Geometric : "Statistics.Distribution.Geometric" -}
 {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -}
-{-# INLINE randomIntSeed #-}
+
 randomIntSeed :: (
     DiscreteGen d, PrimMonad m
   ) => String          -- ^ Index name (one character)
@@ -138,5 +139,5 @@     -> m (Tensor Int)  -- ^ Generated vector
 
 randomIntSeed [i] s = Tensor.randomIntSeed ([i],[s]) ([],[])
-randomIntSeed _ _ = \_ _ -> return $ Err invalidIndices
+randomIntSeed _ _ = \_ _ -> return $ error invalidIndices
 
test/Spec.hs view
@@ -13,5 +13,44 @@     main
 ) where
 
+import           Control.DeepSeq
+import           Multilinear.Generic
+import           Multilinear.Class
+import qualified Multilinear.Matrix as Matrix
+import qualified Multilinear.Vector as Vector
+
+v_i :: Tensor Double
+v_i = Vector.fromIndices "i" 10 fromIntegral
+
+v_j :: Tensor Double
+v_j = Vector.fromIndices "j" 5 (\x -> fromIntegral x + 5.0)
+
+v_k :: Tensor Double
+v_k = Vector.fromIndices "k" 10 fromIntegral
+
+m_ik :: Tensor Double
+m_ik = Matrix.fromIndices "ik" 10 10 (\i j -> fromIntegral i + fromIntegral j)
+
 main :: IO ()
-main = putStrLn "Test to do..."+main = do
+    putStr "v^i = "
+    print v_i
+    putStr "v^j = "
+    print v_j
+    putStr "v^k = "
+    print v_k
+    putStr "Matrix m_ji = v^j + v_i = "
+    let m = v_j + (v_i \/ "i")
+    print m
+    putStr "m_ji * v^i = "
+    print $ m * v_i
+    putStr "m_ji * v^k = "
+    print $ m * v_k
+    putStr "Matrix m_ik = "
+    print m_ik
+    putStr "m_ik * v^k = "
+    print $ m_ik * v_k
+    putStr "m_ik |>>> i = "
+    print $ m_ik |>>> "i"
+    putStr "m_ji * m_ik"
+    print $ m * m_ik