{-# LANGUAGE Safe #-}
module Copilot.Language.Operators.Integral
( div
, mod
, (^)
) where
import Copilot.Core (Typed, typeOf)
import qualified Copilot.Core as Core
import Copilot.Language.Operators.BitWise ((.<<.))
import Copilot.Language.Stream
import qualified Data.Bits as B
import qualified Prelude as P
import Data.List (foldl', replicate)
div :: (Typed a, P.Integral a) => Stream a -> Stream a -> Stream a
(Const 0) div :: Stream a -> Stream a -> Stream a
`div` _ = a -> Stream a
forall a. Typed a => a -> Stream a
Const 0
_ `div` (Const 0) = String -> Stream a
forall a. String -> a
Core.badUsage "in div: division by zero."
x :: Stream a
x `div` (Const 1) = Stream a
x
x :: Stream a
x `div` y :: Stream a
y = Op2 a a a -> Stream a -> Stream a -> Stream a
forall a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
Op2 (Type a -> Op2 a a a
forall a. Integral a => Type a -> Op2 a a a
Core.Div Type a
forall a. Typed a => Type a
typeOf) Stream a
x Stream a
y
mod :: (Typed a, P.Integral a) => Stream a -> Stream a -> Stream a
_ mod :: Stream a -> Stream a -> Stream a
`mod` (Const 0) = String -> Stream a
forall a. String -> a
Core.badUsage "in mod: division by zero."
(Const 0) `mod` _ = (a -> Stream a
forall a. Typed a => a -> Stream a
Const 0)
(Const x :: a
x) `mod` (Const y :: a
y) = a -> Stream a
forall a. Typed a => a -> Stream a
Const (a
x a -> a -> a
forall a. Integral a => a -> a -> a
`P.mod` a
y)
x :: Stream a
x `mod` y :: Stream a
y = Op2 a a a -> Stream a -> Stream a -> Stream a
forall a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
Op2 (Type a -> Op2 a a a
forall a. Integral a => Type a -> Op2 a a a
Core.Mod Type a
forall a. Typed a => Type a
typeOf) Stream a
x Stream a
y
(^) :: (Typed a, Typed b, P.Num a, B.Bits a, P.Integral b)
=> Stream a -> Stream b -> Stream a
(Const 0) ^ :: Stream a -> Stream b -> Stream a
^ (Const 0) = a -> Stream a
forall a. Typed a => a -> Stream a
Const 1
(Const 0) ^ x :: Stream b
x = Op3 Bool a a a -> Stream Bool -> Stream a -> Stream a -> Stream a
forall a b c d.
(Typed a, Typed b, Typed c, Typed d) =>
Op3 a b c d -> Stream a -> Stream b -> Stream c -> Stream d
Op3 (Type a -> Op3 Bool a a a
forall b. Type b -> Op3 Bool b b b
Core.Mux Type a
forall a. Typed a => Type a
typeOf) (Op2 b b Bool -> Stream b -> Stream b -> Stream Bool
forall a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
Op2 (Type b -> Op2 b b Bool
forall a. Eq a => Type a -> Op2 a a Bool
Core.Eq Type b
forall a. Typed a => Type a
typeOf) Stream b
x 0) (1) (0)
(Const 1) ^ _ = a -> Stream a
forall a. Typed a => a -> Stream a
Const 1
(Const x :: a
x) ^ (Const y :: b
y) = a -> Stream a
forall a. Typed a => a -> Stream a
Const (a
x a -> b -> a
forall a b. (Num a, Integral b) => a -> b -> a
P.^ b
y)
(Const 2) ^ y :: Stream b
y = (a -> Stream a
forall a. Typed a => a -> Stream a
Const 1) Stream a -> Stream b -> Stream a
forall a b.
(Bits a, Typed a, Typed b, Integral b) =>
Stream a -> Stream b -> Stream a
.<<. Stream b
y
x :: Stream a
x ^ (Const y :: b
y) = (Stream a -> Stream a -> Stream a)
-> Stream a -> [Stream a] -> Stream a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Stream a -> Stream a -> Stream a
forall a. Num a => a -> a -> a
(P.*)) (a -> Stream a
forall a. Typed a => a -> Stream a
Const 1) (Int -> Stream a -> [Stream a]
forall a. Int -> a -> [a]
replicate (b -> Int
forall a b. (Integral a, Num b) => a -> b
P.fromIntegral b
y) Stream a
x)
_ ^ _ = String -> Stream a
forall a. String -> a
Core.badUsage "in ^: in x ^ y, either x must be the constant 2, or y must be a constant. (Do not confuse ^ with bitwise XOR (.^.) or with ** for exponentation of floats/doubles.)"