{-# LANGUAGE FlexibleInstances, CPP #-}
module Data.Matrix.SymmetryOperationsSymbols (
fromMatrix,
fromMatrix',
readMatrix,
readMatrix',
toMatrix,
toMatrixHex,
notHexagonal,
hexagonal,
liftError,
) where
import Data.Ratio (Ratio)
import Data.Matrix (Matrix,detLU,trace,identity)
import Text.ParserCombinators.Parsec (ParseError,parse)
import Data.Matrix.SymmetryOperationsSymbols.Common
import Data.Matrix.SymmetryOperationsSymbols.UnitMatrixCase
import Data.Matrix.SymmetryOperationsSymbols.GlideOrReflectionCase
import Data.Matrix.SymmetryOperationsSymbols.RotationCase
import Data.Matrix.SymmetryOperationsSymbols.RotInversionCase
import Data.Matrix.SymmetryOperationsSymbols.Parser
import Data.Matrix.SymmetryOperationsSymbols.SymopGeom
import Data.Matrix.SymmetryOperationsSymbols.Calc
import Data.Matrix.SymmetryOperationsSymbols.PlainText
import Data.Matrix.AsXYZ (fromXYZ,prettyXYZ)
#if MIN_VERSION_base(4,13,0)
import Control.Monad.Fail (MonadFail(..))
instance MonadFail (Either String) where
fail = Left
#endif
fromMatrix :: Integral a =>
Matrix (Ratio a)
-> Either String String
fromMatrix = fromMatrix'
#if MIN_VERSION_base(4,13,0)
fromMatrix' :: (Integral a, MonadFail f) => Matrix (Ratio a) -> f String
#else
fromMatrix' :: (Monad m, Integral a) => Matrix (Ratio a) -> m String
#endif
fromMatrix' m = showAsPlainText <$> readMatrix' m
readMatrix :: Integral a =>
Matrix (Ratio a)
-> Maybe (SymopGeom a)
readMatrix = readMatrix'
#if MIN_VERSION_base(4,13,0)
readMatrix' :: (MonadFail m, Integral a) => Matrix (Ratio a) -> m (SymopGeom a)
#else
readMatrix' :: (Monad m, Integral a) => Matrix (Ratio a) -> m (SymopGeom a)
#endif
readMatrix' m
| rotPart m == identity 3 = unitMatrixCase m
| correpondToRotInversion tr det = rotInversionCase m
| correpondToNFoldRotation tr det = nFoldRotationCase m
| correpondToGlideOrReflection tr det = glideOrReflectionCase m
| otherwise = fail $ "coordinate triplet '" ++ prettyXYZ m ++ "' is not symmetry operation."
where
tr = trace (rotPart m)
det = detLU (rotPart m)
toMatrix :: Integral a =>
String
-> Either ParseError (Matrix (Ratio a))
toMatrix st = parse notHexagonal st st
toMatrixHex :: Integral a =>
String
-> Either ParseError (Matrix (Ratio a))
toMatrixHex st = parse hexagonal st st
#if MIN_VERSION_base(4,13,0)
liftError :: MonadFail m => Either ParseError a -> m a
#else
liftError :: Monad m => Either ParseError a -> m a
#endif
liftError (Left s) = fail ""
liftError (Right m) = return m