{-# LANGUAGE FlexibleContexts #-} module Jikka.Core.Language.Runtime where import Jikka.Common.Error floorDiv :: MonadError Error m => Integer -> Integer -> m Integer floorDiv :: Integer -> Integer -> m Integer floorDiv Integer _ Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError String "zero div" floorDiv Integer a Integer b = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer a Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `div` Integer b) floorMod :: MonadError Error m => Integer -> Integer -> m Integer floorMod :: Integer -> Integer -> m Integer floorMod Integer _ Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError String "zero div" floorMod Integer a Integer b = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer a Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `mod` Integer b) ceilDiv :: MonadError Error m => Integer -> Integer -> m Integer ceilDiv :: Integer -> Integer -> m Integer ceilDiv Integer _ Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError String "zero div" ceilDiv Integer a Integer b = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return ((Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer b Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer 1) Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `div` Integer b) ceilMod :: MonadError Error m => Integer -> Integer -> m Integer ceilMod :: Integer -> Integer -> m Integer ceilMod Integer _ Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError String "zero div" ceilMod Integer a Integer b = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a - ((Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer b Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer 1) Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `div` Integer b) Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer b) modinv :: MonadError Error m => Integer -> Integer -> m Integer modinv :: Integer -> Integer -> m Integer modinv Integer a Integer m | Integer m Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer 0 Bool -> Bool -> Bool || Integer a Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `mod` Integer m Integer -> Integer -> Bool forall a. Eq a => a -> a -> Bool == Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError (String -> m Integer) -> String -> m Integer forall a b. (a -> b) -> a -> b $ String "invalid argument for inv: " String -> String -> String forall a. [a] -> [a] -> [a] ++ (Integer, Integer) -> String forall a. Show a => a -> String show (Integer a, Integer m) modinv Integer a Integer m = Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> m Integer forall (m :: * -> *). MonadError Error m => Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> m Integer go Integer a Integer m Integer 0 Integer 1 Integer 1 Integer 0 where go :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> m Integer go Integer 0 Integer b Integer x Integer y Integer _ Integer _ = if Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer x Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer m Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer y Integer -> Integer -> Bool forall a. Eq a => a -> a -> Bool == Integer b Bool -> Bool -> Bool && Integer b Integer -> Integer -> Bool forall a. Eq a => a -> a -> Bool == Integer 1 then Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return Integer x else String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError String "Jikka.Core.Language.Runtime.modinv: something wrong" go Integer a Integer b Integer x Integer y Integer u Integer v = let q :: Integer q = Integer b Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `div` Integer a in Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> m Integer go (Integer b Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer q Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer a) Integer a Integer u Integer v (Integer x Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer q Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer u) (Integer y Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer q Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer v) modpow :: MonadError Error m => Integer -> Integer -> Integer -> m Integer modpow :: Integer -> Integer -> Integer -> m Integer modpow Integer _ Integer _ Integer m | Integer m Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError (String -> m Integer) -> String -> m Integer forall a b. (a -> b) -> a -> b $ String "invalid argument for modpow: MOD = " String -> String -> String forall a. [a] -> [a] -> [a] ++ Integer -> String forall a. Show a => a -> String show Integer m modpow Integer a Integer b Integer m = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer -> m Integer) -> Integer -> m Integer forall a b. (a -> b) -> a -> b $ Integer -> Integer -> Integer go (Integer a Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `mod` Integer m) Integer b where go :: Integer -> Integer -> Integer go Integer a Integer 0 = Integer a go Integer a Integer b = Integer -> Integer -> Integer go (if Integer b Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `mod` Integer 2 Integer -> Integer -> Bool forall a. Eq a => a -> a -> Bool == Integer 1 then Integer a Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer b Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `mod` Integer m else Integer a) (Integer b Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `div` Integer 2) fact :: MonadError Error m => Integer -> m Integer fact :: Integer -> m Integer fact Integer n | Integer n Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool < Integer 0 = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError (String -> m Integer) -> String -> m Integer forall a b. (a -> b) -> a -> b $ String "invalid argument for fact: " String -> String -> String forall a. [a] -> [a] -> [a] ++ Integer -> String forall a. Show a => a -> String show Integer n fact Integer n = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer -> m Integer) -> Integer -> m Integer forall a b. (a -> b) -> a -> b $ [Integer] -> Integer forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a product [Integer 1 .. Integer n] choose :: MonadError Error m => Integer -> Integer -> m Integer choose :: Integer -> Integer -> m Integer choose Integer n Integer r | Bool -> Bool not (Integer 0 Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer r Bool -> Bool -> Bool && Integer r Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer n) = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError (String -> m Integer) -> String -> m Integer forall a b. (a -> b) -> a -> b $ String "invalid argument for choose: " String -> String -> String forall a. [a] -> [a] -> [a] ++ (Integer, Integer) -> String forall a. Show a => a -> String show (Integer n, Integer r) choose Integer n Integer r = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer -> m Integer) -> Integer -> m Integer forall a b. (a -> b) -> a -> b $ [Integer] -> Integer forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a product [Integer n Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer r Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer 1 .. Integer n] Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `div` [Integer] -> Integer forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a product [Integer 1 .. Integer r] permute :: MonadError Error m => Integer -> Integer -> m Integer permute :: Integer -> Integer -> m Integer permute Integer n Integer r | Bool -> Bool not (Integer 0 Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer r Bool -> Bool -> Bool && Integer r Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer n) = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError (String -> m Integer) -> String -> m Integer forall a b. (a -> b) -> a -> b $ String "invalid argument for choose: " String -> String -> String forall a. [a] -> [a] -> [a] ++ (Integer, Integer) -> String forall a. Show a => a -> String show (Integer n, Integer r) permute Integer n Integer r = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return (Integer -> m Integer) -> Integer -> m Integer forall a b. (a -> b) -> a -> b $ [Integer] -> Integer forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a product [Integer n Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer r Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer 1 .. Integer n] multichoose :: MonadError Error m => Integer -> Integer -> m Integer multichoose :: Integer -> Integer -> m Integer multichoose Integer n Integer r | Bool -> Bool not (Integer 0 Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer r Bool -> Bool -> Bool && Integer r Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool <= Integer n) = String -> m Integer forall (m :: * -> *) a. MonadError Error m => String -> m a throwRuntimeError (String -> m Integer) -> String -> m Integer forall a b. (a -> b) -> a -> b $ String "invalid argument for multichoose: " String -> String -> String forall a. [a] -> [a] -> [a] ++ (Integer, Integer) -> String forall a. Show a => a -> String show (Integer n, Integer r) multichoose Integer 0 Integer 0 = Integer -> m Integer forall (m :: * -> *) a. Monad m => a -> m a return Integer 1 multichoose Integer n Integer r = Integer -> Integer -> m Integer forall (m :: * -> *). MonadError Error m => Integer -> Integer -> m Integer choose (Integer n Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer r Integer -> Integer -> Integer forall a. Num a => a -> a -> a - Integer 1) Integer r