-- Copyright (c) 2010, David Amos. All rights reserved. {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-} module Math.Algebras.LaurentPoly where import Math.Algebra.Field.Base hiding (powers) import Math.Algebras.VectorSpace import Math.Algebras.TensorProduct import Math.Algebras.Structures import qualified Data.List as L import Math.Algebras.Commutative -- for DivisionBasis and quotRemMP -- LAURENT MONOMIALS data LaurentMonomial = LM Int [(String,Int)] deriving (Eq,Ord) {- instance Ord LaurentMonomial where compare (LM si xis) (LM sj yjs) = compare (-si, xis) (-sj, yjs) -} instance Show LaurentMonomial where show (LM 0 []) = "1" show (LM _ xis) = concatMap (\(x,i) -> if i==1 then x else x ++ "^" ++ show i) xis instance Mon LaurentMonomial where munit = LM 0 [] mmult (LM si xis) (LM sj yjs) = LM (si+sj) $ addmerge xis yjs instance (Eq k, Num k) => Algebra k LaurentMonomial where unit 0 = zerov -- V [] unit x = V [(munit,x)] mult (V ts) = nf $ fmap (\(a,b) -> a `mmult` b) (V ts) -- mult (V ts) = nf $ V [(a `mmult` b, x) | (T a b, x) <- ts] {- -- This is just the Set Coalgebra, so better to use a generic instance -- Also, not used anywhere. Hence commented out instance Num k => Coalgebra k LaurentMonomial where counit (V ts) = sum [x | (m,x) <- ts] -- trace comult = fmap (\m -> T m m) -} type LaurentPoly k = Vect k LaurentMonomial lvar v = V [(LM 1 [(v,1)], 1)] :: LaurentPoly Q instance (Eq k, Fractional k) => Fractional (LaurentPoly k) where recip (V [(LM si xis,c)]) = V [(LM (-si) $ map (\(x,i)->(x,-i)) xis, recip c)] recip _ = error "LaurentPoly.recip: only defined for single terms" q = lvar "q" q' = 1/q {- -- division doesn't terminate with the derived Ord instance -- if we use the graded Ord instance instead, division doesn't continue into negative powers -- so we get the negative powers as remained, even if they're divisible instance DivisionBasis LaurentMonomial where dividesB (LM si xis) (LM sj yjs) = si <= sj && dividesB' xis yjs where dividesB' ((x,i):xis) ((y,j):yjs) = case compare x y of LT -> False GT -> dividesB' ((x,i):xis) yjs EQ -> if i<=j then dividesB' xis yjs else False dividesB' [] _ = True dividesB' _ [] = False divB (LM si xis) (LM sj yjs) = LM (si-sj) $ divB' xis yjs where divB' ((x,i):xis) ((y,j):yjs) = case compare x y of LT -> (x,i) : divB' xis ((y,j):yjs) EQ -> if i == j then divB' xis yjs else (x,i-j) : divB' xis yjs -- we don't bother to check i > j GT -> error "divB'" -- (y,-j) : divB' ((x,i):xis) yjs divB' xis [] = xis divB' [] yjs = error "divB'" -}