packages feed

egison-5.1.0: hs-src/Language/Egison/PrettyMath/Latex.hs

{- |
Module      : Language.Egison.PrettyMath.Latex
Licence     : MIT
-}

module Language.Egison.PrettyMath.Latex
  ( showMathValue
  ) where

import           Data.List                      (intercalate)

import           Language.Egison.PrettyMath.AST

showMathValue :: MathValue -> String
showMathValue (Atom a []) = a
showMathValue (Atom a xs) = a ++ showMathValueScript xs
showMathValue (Partial f xs) = "\\frac{" ++ convertToPartial (f, length xs) ++ "}{" ++ showPartial xs ++ "}"
 where
  showPartial :: [MathValue] -> String
  showPartial xs = case elemCount xs of
    []      -> ""
    (l:lx)  -> convertToPartial2 l ++ foldr (\x acc -> " " ++ convertToPartial2 x ++ acc) "" lx

  convertToPartial :: (MathValue, Int) -> String
  convertToPartial (x, 1) = "\\partial " ++ showMathValue x
  convertToPartial (x, n) = "\\partial^" ++ show n ++ " " ++ showMathValue x

  convertToPartial2 :: (MathValue, Int) -> String
  convertToPartial2 (x, 1) = "\\partial " ++ showMathValue x
  convertToPartial2 (x, n) = "\\partial " ++ showMathValue x ++ "^"  ++ show n
showMathValue (NegativeAtom a) = "-" ++ a
showMathValue (Plus []) = ""
showMathValue (Plus (x:xs)) = showMathValue x ++ showMathValueForPlus xs
 where
  showMathValueForPlus :: [MathValue] -> String
  showMathValueForPlus []                                  = ""
  showMathValueForPlus (NegativeAtom a:xs)                 = " - " ++ a ++ showMathValueForPlus xs
  showMathValueForPlus (Multiply (NegativeAtom "1":ys):xs) = " - " ++ showMathValue (Multiply ys) ++ showMathValueForPlus xs
  showMathValueForPlus (Multiply (NegativeAtom a:ys):xs)   = " - " ++ showMathValue (Multiply (Atom a []:ys)) ++ showMathValueForPlus xs
  showMathValueForPlus (x:xs)                              = " + " ++  showMathValue x ++ showMathValueForPlus xs
showMathValue (Multiply []) = ""
showMathValue (Multiply [x]) = showMathValue x
showMathValue (Multiply (Atom "1" []:xs)) = showMathValue (Multiply xs)
showMathValue (Multiply (NegativeAtom "1":xs)) = "-" ++ showMathValue (Multiply xs)
showMathValue (Multiply (x:xs)) = showMathValue' x ++ " " ++ showMathValue (Multiply xs)
showMathValue (Div x y) = "\\frac{" ++ showMathValue x ++ "}{" ++ showMathValue y ++ "}"
showMathValue (Power lv1 lv2) = showMathValue' lv1 ++ "^{" ++ showMathValue lv2 ++ "}"
showMathValue (Func (Atom "sqrt" []) [x]) = "\\sqrt{" ++ showMathValue x ++ "}"
showMathValue (Func (Atom "rt" []) [x, y]) = "\\sqrt[" ++ showMathValue x ++ "]{" ++ showMathValue y ++ "}"
showMathValue (Func (Atom "exp" []) [x]) = "e^{" ++ showMathValue x ++ "}"
showMathValue (Func (Atom fn []) xs) | fn `elem` latexMathOperators =
  "\\" ++ fn ++ "(" ++ showMathValueArg xs ", " ++ ")"
showMathValue (Func f xs) = showMathValue f ++ "(" ++ showMathValueArg xs ", " ++ ")"
showMathValue (Tensor xs mis) = "\\begin{pmatrix} " ++ showMathValueVectors xs ++ "\\end{pmatrix}" ++ showMathValueScript mis
showMathValue (Tuple xs) = "(" ++ showMathValueArg xs ", " ++ ")"
showMathValue (Collection xs) = "\\{" ++ showMathValueArg xs ", " ++ "\\}"
showMathValue (Quote x) = "(" ++ showMathValue x ++ ")"

showMathValue' :: MathValue -> String
showMathValue' (Plus xs) = "(" ++ showMathValue (Plus xs) ++ ")"
showMathValue' x         = showMathValue x

showMathValueArg :: [MathValue] -> String -> String
showMathValueArg exprs sep = intercalate sep $ map showMathValue exprs

-- Standard LaTeX math operators that must be typeset upright with a
-- backslash-prefixed control sequence (e.g. \sin instead of an italic "sin").
latexMathOperators :: [String]
latexMathOperators =
  [ "sin", "cos", "tan", "cot", "sec", "csc"
  , "sinh", "cosh", "tanh", "coth"
  , "log", "ln", "arcsin", "arccos", "arctan" ]

showMathValueSuper :: MathIndex -> String
showMathValueSuper (Super (Atom "#" [])) = "\\#"
showMathValueSuper (Super x)             = showMathValue x
showMathValueSuper (Sub _)               = "\\;"

showMathValueSub :: MathIndex -> String
showMathValueSub (Sub (Atom "#" [])) = "\\#"
showMathValueSub (Sub x)             = showMathValue x
showMathValueSub (Super _)           = "\\;"

showMathValueScript :: [MathIndex] -> String
showMathValueScript [] = ""
showMathValueScript is = "_{" ++ concatMap showMathValueSub is ++ "}^{" ++ concatMap showMathValueSuper is ++ "}"

showMathValueVectors :: [MathValue] -> String
showMathValueVectors []                = ""
showMathValueVectors (Tensor lvs []:r) = showMathValueArg lvs " & " ++ " \\\\ " ++ showMathValueVectors r
showMathValueVectors lvs               = showMathValueArg lvs " \\\\ " ++ "\\\\ "

elemCount :: Eq a => [a] -> [(a, Int)]
elemCount []     = []
elemCount (x:xs) = (x, length (filter (== x) xs) + 1) : elemCount (filter (/= x) xs)