module MagicHaskeller.LibExcelStaged where
import MagicHaskeller
import Data.List
import Data.Char
default (Int, Integer, Double)
totalGCD x y = gcd' (abs x) (abs y)
where gcd' a 0 = a
gcd' a b = gcd' b (a `rem` b)
curry2 = curry
curry3 :: ((a,b,c) -> d) -> a->b->c->d
curry3 f x y z = f(x,y,z)
curry4 :: ((a,b,c,d) -> e) -> a->b->c->d->e
curry4 f w x y z = f(w,x,y,z)
curry5 :: ((a,b,c,d,e) -> f) -> a->b->c->d->e->f
curry5 f v w x y z = f(v,w,x,y,z)
curry6 :: ((a,b,c,d,e,f) -> g) -> a->b->c->d->e->f->g
curry6 f u v w x y z = f(u,v,w,x,y,z)
iF :: (Bool, a, a) -> a
iF (True, t, f) = t
iF (False, t, f) = f
upper = map toUpper
lower = map toLower
proper "" = ""
proper (c:cs) | isAlpha c = toUpper c : case span isAlpha cs of (ts, ds) -> map toLower ts ++ proper ds
| otherwise = c : proper cs
right, left :: ([b], Int) -> [b]
left1 = take 1
right1 str = right (str, 1)
left (b, a) = take a b
right (b, a) = reverse (take a (reverse b))
dropLeft b a = right(b, len(b) a)
mid (c, a, b) = take b (drop (a 1) c)
len :: Num a => String -> a
len = fromIntegral . length
concatenate (a, b) = a ++ b
concatenatE (a,b,c) = a++b++c
concatenaTE (a,b,c,d) = a++b++c++d
concatenATE (a,b,c,d,e) = a++b++c++d++e
concateNATE (a,b,c,d,e,f) = a++b++c++d++e++f
cEILING, fLOOR, mround :: (Double, Double) -> Double
cEILING (_, 0) = 0
cEILING (a, b) = fromIntegral (Prelude.ceiling (a / b))*b
mround (_, 0) = 0
mround (a, b) = fromIntegral (Prelude.round (a / b))*b
fLOOR0 a b | b <= 0 = 0
| otherwise = fromIntegral (Prelude.floor (a / b))*b
fLOOR (0, 0) = 0
fLOOR (a, b) | b <= 0 = 0/0
| otherwise = fLOOR0 a b
rOUND, roundup, rounddown :: (Double, Int) -> Double
rOUND (a, b) = mround (a, 0.1 ^^ b)
roundup (a, b) | a > 0 = cEILING (a, 0.1 ^^ b)
| otherwise = fLOOR0 a (0.1 ^^ b)
rounddown (a, b) | a < 0 = cEILING (a, 0.1 ^^ b)
| otherwise = fLOOR0 a (0.1 ^^ b)
trim = unwords . words
fIND :: (Num b) => (String, String, Int) -> Maybe b
fIND (pat, xs, pos) = fmap (fromIntegral . fst) $ Data.List.find (isPrefixOf pat . snd) $ zip [1..] $ drop (pos1) $ tails xs
ifERROR :: (Maybe a, a) -> a
ifERROR (mb, x) = maybe x id mb
aND (a, b) = a && b
oR (a, b) = a || b
sign :: Num a => a -> a
sign = signum
power (a,b) | isNaN result || isInfinite result = Nothing
| otherwise = Just result
where result = a ** b
sQRT x | x < 0 = Nothing
| otherwise = Just $ sqrt x
lOG(a,b) | a<=0 || b<=0 = Nothing
| otherwise = Just $ logBase b a
ln a | a <= 0 = Nothing
| otherwise = Just $ Prelude.log a
pI () = pi
aTAN2 (x,y) = atan2 y x
fact n | n < 0 = Nothing
| otherwise = Just $ product [1..n]
combin (n,r) | (signum n + 1) * (signum r + 1) * (signum (rn) + 1) == 0 = Nothing
| otherwise = Just $ product [nr+1 .. n] `div` product [1..r]
mOD :: (Int, Int) -> Maybe Int
mOD(_,0) = Nothing
mOD(m,n) = Just $ m `mod` n
degrees = ((180/pi)*)
radians = ((pi/180)*)
gCD (m, n) = totalGCD (truncate m) (truncate n)
findIx c xs n = finD(char(7), sUBSTITUTE(concatenate(c,xs), c, char(7), 1+abs(n)))1
finD(c, xs) = maybe undefined id $ fIND(c, xs, 1)
char = (:"") . chr
sUBsTITUTE :: (String, String, String) -> String
sUBsTITUTE(ts, "", _) = ts
sUBsTITUTE([], _, _) = []
sUBsTITUTE(text@(t:ts), old, new) = case old `stripPrefix` text of Nothing -> t : sUBsTITUTE(ts, old, new)
Just rest -> new ++ sUBsTITUTE(rest, old, new)
sUBSTITUTE :: (String, String, String, Int) -> String
sUBSTITUTE(text, old, new, num) | num <= 0 = error "#NUM"
| otherwise = if null old then text
else sUB text old new num
sUB "" _ _ _ = ""
sUB text@(t:ts) old new n = case old `stripPrefix` text of Nothing -> t : sUB ts old new n
Just rest | n<=1 -> new ++ rest
| otherwise -> old ++ sUB rest old new (n1)
sUBST4 :: String -> String -> String -> Int -> String
sUBST4 text old new num = sUBSTITUTE(text, old, new, 1+abs(num))
countStr :: Num a => String -> String -> a
countStr x "" = 0
countStr x str = fromIntegral $ (length(x)length(sUBsTITUTE(x,str,""))) `div` length (str)
$(mkCurriedDecls "'2" [|curry2|] [|(left,right,concatenate,cEILING,mround,rOUND,roundup,rounddown,ifERROR,aND,oR,power,lOG,aTAN2,combin,mOD,gCD)|])
$(mkCurriedDecls "'3" [|curry3|] [|(iF,mid,fIND,sUBsTITUTE,concatenatE)|])
$(mkCurriedDecls "'4" [|curry4|] [|concatenaTE|])
$(mkCurriedDecls "'5" [|curry5|] [|concatenATE|])
$(mkCurriedDecls "'6" [|curry6|] [|concateNATE|])