{-| Module : Multilinear.NForm Description : N-Forms, dot and cross product and determinant Copyright : (c) Artur M. Brodzki, 2018 License : GLP-3 Maintainer : artur@brodzki.org Stability : experimental Portability : Windows/POSIX - This module provides convenient constructors that generates n-forms (tensors with n lower indices with finite or infinite size). - Finitely-dimensional n-forms provide much greater performance than infinitely-dimensional -} module Multilinear.NForm ( -- * Generators Multilinear.NForm.fromIndices, Multilinear.NForm.const, Multilinear.NForm.randomDouble, Multilinear.NForm.randomDoubleSeed, Multilinear.NForm.randomInt, Multilinear.NForm.randomIntSeed, -- * Common cases Multilinear.NForm.dot, Multilinear.NForm.cross ) where import Control.Monad.Primitive import Multilinear.Generic import qualified Multilinear.Tensor as Tensor import Statistics.Distribution invalidIndices :: String invalidIndices = "Indices and its sizes incompatible with n-form structure!" invalidCrossProductIndices :: String invalidCrossProductIndices = "Indices and its sizes incompatible with cross product structure!" {-| Generate N-form as function of its indices -} {-# INLINE fromIndices #-} fromIndices :: ( Num a ) => String -- ^ Indices names (one characted per index) -> [Int] -- ^ Indices sizes -> ([Int] -> a) -- ^ Generator function -> Tensor a -- ^ Generated N-form 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 ) => String -- ^ Indices names (one characted per index) -> [Int] -- ^ Indices sizes -> a -- ^ N-form elements value -> Tensor a -- ^ Generated N-form const d ds = Tensor.const ([],[]) (d,ds) {-| Generate n-vector with random real components with given probability distribution. The n-vector is wrapped in the IO monad. -} {-| Available probability distributions: -} {-| - Beta : "Statistics.Distribution.BetaDistribution" -} {-| - Cauchy : "Statistics.Distribution.CauchyLorentz" -} {-| - Chi-squared : "Statistics.Distribution.ChiSquared" -} {-| - Exponential : "Statistics.Distribution.Exponential" -} {-| - Gamma : "Statistics.Distribution.Gamma" -} {-| - Geometric : "Statistics.Distribution.Geometric" -} {-| - Normal : "Statistics.Distribution.Normal" -} {-| - StudentT : "Statistics.Distribution.StudentT" -} {-| - Uniform : "Statistics.Distribution.Uniform" -} {-| - F : "Statistics.Distribution.FDistribution" -} {-| - Laplace : "Statistics.Distribution.Laplace" -} {-# INLINE randomDouble #-} randomDouble :: ( ContGen d ) => String -- ^ Indices names (one character per index) -> [Int] -- ^ Indices sizes -> d -- ^ Continuous probability distribution (as from "Statistics.Distribution") -> IO (Tensor Double) -- ^ Generated linear functional randomDouble d ds = Tensor.randomDouble ([],[]) (d,ds) {-| Generate n-vector with random integer components with given probability distribution. The n-vector is wrapped in the IO monad. -} {-| Available probability distributions: -} {-| - Binomial : "Statistics.Distribution.Binomial" -} {-| - Poisson : "Statistics.Distribution.Poisson" -} {-| - Geometric : "Statistics.Distribution.Geometric" -} {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -} {-# INLINE randomInt #-} randomInt :: ( DiscreteGen d ) => String -- ^ Indices names (one character per index) -> [Int] -- ^ Indices sizes -> d -- ^ Discrete probability distribution (as from "Statistics.Distribution") -> IO (Tensor Int) -- ^ Generated n-vector randomInt d ds = Tensor.randomInt ([],[]) (d,ds) {-| Generate n-vector with random real components with given probability distribution and given seed. The form is wrapped in a monad. -} {-| Available probability distributions: -} {-| - Beta : "Statistics.Distribution.BetaDistribution" -} {-| - Cauchy : "Statistics.Distribution.CauchyLorentz" -} {-| - Chi-squared : "Statistics.Distribution.ChiSquared" -} {-| - Exponential : "Statistics.Distribution.Exponential" -} {-| - Gamma : "Statistics.Distribution.Gamma" -} {-| - Geometric : "Statistics.Distribution.Geometric" -} {-| - Normal : "Statistics.Distribution.Normal" -} {-| - StudentT : "Statistics.Distribution.StudentT" -} {-| - Uniform : "Statistics.Distribution.Uniform" -} {-| - F : "Statistics.Distribution.FDistribution" -} {-| - Laplace : "Statistics.Distribution.Laplace" -} {-# INLINE randomDoubleSeed #-} randomDoubleSeed :: ( ContGen d, PrimMonad m ) => String -- ^ Index name (one character) -> [Int] -- ^ Number of elements -> d -- ^ Continuous probability distribution (as from "Statistics.Distribution") -> Int -- ^ Randomness seed -> m (Tensor Double) -- ^ Generated n-vector randomDoubleSeed d ds = Tensor.randomDoubleSeed ([],[]) (d,ds) {-| Generate n-vector with random integer components with given probability distribution and given seed. The form is wrapped in a monad. -} {-| Available probability distributions: -} {-| - Binomial : "Statistics.Distribution.Binomial" -} {-| - Poisson : "Statistics.Distribution.Poisson" -} {-| - Geometric : "Statistics.Distribution.Geometric" -} {-| - Hypergeometric: "Statistics.Distribution.Hypergeometric" -} {-# INLINE randomIntSeed #-} randomIntSeed :: ( DiscreteGen d, PrimMonad m ) => String -- ^ Index name (one character) -> [Int] -- ^ Number of elements -> d -- ^ Discrete probability distribution (as from "Statistics.Distribution") -> Int -- ^ Randomness seed -> m (Tensor Int) -- ^ Generated n-vector randomIntSeed d ds = Tensor.randomIntSeed ([],[]) (d,ds) {-| 2-form representing a dot product -} {-# INLINE dot #-} dot :: ( Num 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 {-| 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 ) => String -- ^ Indices names (one characted per index) -> Int -- ^ Size of tensor (dot product is a square tensor) -> Tensor a -- ^ Generated dot product cross [i,j,k] size = Tensor.fromIndices ([i],[size]) ([j,k],[size,size]) (\[_] [_,_] -> 0) cross _ _ = Err invalidCrossProductIndices