diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-03-01 05:15:23 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-03-01 05:15:23 +0100 |
| commit | 74740f0e493a174552d79c3bbd2ab7786f18eb39 (patch) | |
| tree | 483ab2b90f4d00ac62f20fa2308fd2cd55063f82 /rpn.hs | |
| parent | 1554095368e65bf6f1c4d0f0106ae4516117964a (diff) | |
| download | gausshs-master.tar gausshs-master.tar.gz gausshs-master.tar.bz2 gausshs-master.tar.xz gausshs-master.zip | |
Diffstat (limited to 'rpn.hs')
| -rwxr-xr-x | rpn.hs | 28 |
1 files changed, 18 insertions, 10 deletions
| @@ -1,5 +1,7 @@ | |||
| 1 | #!/usr/bin/env runghc | 1 | #!/usr/bin/env runghc |
| 2 | 2 | ||
| 3 | {-# LANGUAGE ViewPatterns #-} | ||
| 4 | |||
| 3 | import Control.Monad (join, sequence, forever) | 5 | import Control.Monad (join, sequence, forever) |
| 4 | import Control.Applicative | 6 | import Control.Applicative |
| 5 | import System.Environment | 7 | import System.Environment |
| @@ -10,7 +12,7 @@ import qualified Control.Monad.State as S | |||
| 10 | import qualified Data.Map as M | 12 | import qualified Data.Map as M |
| 11 | import System.IO | 13 | import System.IO |
| 12 | 14 | ||
| 13 | data Symbol a = Number a a | Err | Add | Sub | Mult | Div | Unc | Exp deriving (Eq, Ord, Show) | 15 | data Symbol a = Number a a | Err | Add | Sub | Mult | Div | Unc | Exp | Pow deriving (Eq, Ord, Show) |
| 14 | instance Floating a => Num (Symbol a) where | 16 | instance Floating a => Num (Symbol a) where |
| 15 | (Number x del) + (Number y del') = Number (x + y) (abs $ gMean [del, del']) | 17 | (Number x del) + (Number y del') = Number (x + y) (abs $ gMean [del, del']) |
| 16 | _ + _ = Err | 18 | _ + _ = Err |
| @@ -42,7 +44,7 @@ fromSymbol _ = (0, 0) | |||
| 42 | 44 | ||
| 43 | 45 | ||
| 44 | pPrint :: (Show a, Fractional a) => Symbol a -> String | 46 | pPrint :: (Show a, Fractional a) => Symbol a -> String |
| 45 | pPrint (Number x d) = (show x) ++ " ± " ++ (show d) ++ " (relative error: " ++ (show $ d / x) ++ ")" | 47 | pPrint (Number x d) = x `seq` d `seq` (show x) ++ " ± " ++ (show d) ++ " (relative error: " ++ (show $ d / x) ++ ")" |
| 46 | pPrint s = show s | 48 | pPrint s = show s |
| 47 | 49 | ||
| 48 | main :: IO () | 50 | main :: IO () |
| @@ -71,7 +73,7 @@ clarifySymbol s = maybe clarify' (return . words) =<< lookupEnv s | |||
| 71 | 73 | ||
| 72 | isKnownSymbol :: String -> Bool | 74 | isKnownSymbol :: String -> Bool |
| 73 | isKnownSymbol s = or [ | 75 | isKnownSymbol s = or [ |
| 74 | s `elem` ["+", "-", "*", "/", "±", "+-", "e"], | 76 | s `elem` ["+", "-", "*", "/", "±", "+-", "e", "^"], |
| 75 | isJust $ (maybeRead s :: Maybe Double) | 77 | isJust $ (maybeRead s :: Maybe Double) |
| 76 | ] | 78 | ] |
| 77 | 79 | ||
| @@ -91,17 +93,18 @@ interpreteSymbol "/" = Div | |||
| 91 | interpreteSymbol "±" = Unc | 93 | interpreteSymbol "±" = Unc |
| 92 | interpreteSymbol "+-" = Unc | 94 | interpreteSymbol "+-" = Unc |
| 93 | interpreteSymbol "e" = Exp | 95 | interpreteSymbol "e" = Exp |
| 96 | interpreteSymbol "^" = Pow | ||
| 94 | interpreteSymbol x = Number (read x) 0 | 97 | interpreteSymbol x = Number (read x) 0 |
| 95 | 98 | ||
| 96 | evalExpVec :: Floating a => [Symbol a] -> Symbol a | 99 | evalExpVec :: (Floating a, RealFrac a, Eq a) => [Symbol a] -> Symbol a |
| 97 | evalExpVec is = head . snd $ S.runState (evalExpVec' is) [] | 100 | evalExpVec is = head . snd $ S.runState (evalExpVec' is) [] |
| 98 | 101 | ||
| 99 | evalExpVec' :: Floating a => [Symbol a] -> S.State [Symbol a] () | 102 | evalExpVec' :: (Floating a, RealFrac a, Eq a) => [Symbol a] -> S.State [Symbol a] () |
| 100 | evalExpVec' is = do | 103 | evalExpVec' is = do |
| 101 | sequence $ map evalExp is | 104 | sequence $ map evalExp is |
| 102 | return () | 105 | return () |
| 103 | 106 | ||
| 104 | evalExp :: Floating a => Symbol a -> S.State [Symbol a] () | 107 | evalExp :: (Floating a, RealFrac a, Eq a) => Symbol a -> S.State [Symbol a] () |
| 105 | evalExp (Number x del) = do | 108 | evalExp (Number x del) = do |
| 106 | state <- S.get | 109 | state <- S.get |
| 107 | S.put $ ((Number x del):state) | 110 | S.put $ ((Number x del):state) |
| @@ -121,8 +124,13 @@ evalExp Div = do | |||
| 121 | state <- S.get | 124 | state <- S.get |
| 122 | S.put $ ((foldl1 (/) . reverse $ take 2 state):drop 2 state) | 125 | S.put $ ((foldl1 (/) . reverse $ take 2 state):drop 2 state) |
| 123 | evalExp Exp = do | 126 | evalExp Exp = do |
| 124 | state <- S.get | 127 | (e:b:state) <- S.get |
| 128 | S.put $ (b * (Number (10 ** (fst $ fromSymbol e)) 0)):state | ||
| 129 | evalExp Pow = do | ||
| 130 | ((Number b'@(round -> b) 0):(Number y dY):(Number a'@(round -> a) 0):(Number x dX):state) <- S.get | ||
| 125 | let | 131 | let |
| 126 | b = state !! 1 | 132 | prod = (x^^a) * (y^^b) |
| 127 | e = state !! 0 | 133 | dX' = dX / x |
| 128 | S.put $ ((b * (Number (10 ** (fst $ fromSymbol e)) 0)):drop 2 state) | 134 | dY' = dY / y |
| 135 | err = prod * (sqrt $ (a' * dX')^2 + (b' * dY')^2) | ||
| 136 | S.put $ (Number prod err):state | ||
