```{-# LANGUAGE UndecidableInstances, MultiParamTypeClasses, FlexibleInstances #-}
-----------------------------------------------------------------------------
{- |
Module      :  Numeric.LinearAlgebra.Linear
Copyright   :  (c) Alberto Ruiz 2006-7

Maintainer  :  Alberto Ruiz (aruiz at um dot es)
Stability   :  provisional
Portability :  uses ffi

Basic optimized operations on vectors and matrices.

-}
-----------------------------------------------------------------------------

module Numeric.LinearAlgebra.Linear (
Linear(..)
) where

import Data.Packed.Vector
import Data.Packed.Matrix
import Data.Complex
import Numeric.GSL.Vector

-- | Basic element-by-element functions.
class (Container c e) => Linear c e where
-- | create a structure with a single element
scalar      :: e -> c e
scale       :: e -> c e -> c e
-- | scale the element by element reciprocal of the object:
--
-- @scaleRecip 2 (fromList [5,i]) == 2 |> [0.4 :+ 0.0,0.0 :+ (-2.0)]@
scaleRecip  :: e -> c e -> c e
addConstant :: e -> c e -> c e
add         :: c e -> c e -> c e
sub         :: c e -> c e -> c e
-- | element by element multiplication
mul         :: c e -> c e -> c e
-- | element by element division
divide      :: c e -> c e -> c e
equal       :: c e -> c e -> Bool

instance Linear Vector Double where
scale = vectorMapValR Scale
scaleRecip = vectorMapValR Recip
sub = vectorZipR Sub
mul = vectorZipR Mul
divide = vectorZipR Div
equal u v = dim u == dim v && vectorMax (vectorMapR Abs (sub u v)) == 0.0
scalar x = fromList [x]

instance Linear Vector (Complex Double) where
scale = vectorMapValC Scale
scaleRecip = vectorMapValC Recip
sub = vectorZipC Sub
mul = vectorZipC Mul
divide = vectorZipC Div
equal u v = dim u == dim v && vectorMax (mapVector magnitude (sub u v)) == 0.0
scalar x = fromList [x]

instance (Linear Vector a, Container Matrix a) => (Linear Matrix a) where
scale x = liftMatrix (scale x)
scaleRecip x = liftMatrix (scaleRecip x)