module QIO.QArith where
import Data.Monoid as Monoid
import QIO.QioSyn
import QIO.Qdata
import QIO.QioClass
import QIO.Qio
import QIO.QExamples
swapQInt :: QInt -> QInt -> U
swapQInt (QInt xs) (QInt ys) = swapQInt' xs ys
where
swapQInt' [] [] = mempty
swapQInt' (x:xs) (y:ys) = (swap x y) `mappend` swapQInt' xs ys
ifElseQ :: Qbit -> U -> U -> U
ifElseQ qa t f = cond qa (\ qa -> if qa then t else f)
ifQ :: Qbit -> U -> U
ifQ qa t = ifElseQ qa t mempty
cnot :: Qbit -> Qbit -> U
cnot qa qb = ifQ qa (unot qb)
addBit :: Qbit -> Qbit -> Qbit -> U
addBit qc qa qb =
cnot qa qb `mappend`
cnot qc qb
carry :: Qbit -> Qbit -> Qbit -> Qbit -> U
carry qci qa qb qcsi =
cond qci (\ ci ->
cond qa (\ a ->
cond qb (\ b ->
if ci && a || ci && b || a && b
then unot qcsi
else mempty)))
addBits :: [Qbit] -> [Qbit] -> Qbit -> U
addBits qas qbs qc' =
letU False (addBits' qas qbs)
where addBits' [] [] qc = ifQ qc (unot qc')
addBits' (qa:qas) (qb:qbs) qc =
letU False (\ qc' -> carry qc qa qb qc' `mappend`
addBits' qas qbs qc'`mappend`
urev (carry qc qa qb qc')) `mappend`
addBit qc qa qb
addBits' :: [Qbit] -> [Qbit] -> [Qbit] -> Qbit -> U
addBits' [] [] [] qc = mempty
addBits' (qa:qas) (qb:qbs) (qc':qcs') qc =
(carry qc qa qb qc' `mappend`
addBits' qas qbs qcs' qc'`mappend`
urev (carry qc qa qb qc')) `mappend`
addBit qc qa qb
adder :: QInt -> QInt -> Qbit -> U
adder (QInt qas) (QInt qbs) qc = addBits qas qbs qc
tadder :: (Int,(Int,Bool)) -> QIO (Int,(Int,Bool))
tadder xyc = do q @ (qx,(qy,qc)) <- mkQ xyc
applyU (adder qx qy qc)
xyc <- measQ q
return xyc
tRadder :: (Int,(Int,Bool)) -> QIO (Int,(Int,Bool))
tRadder xyc = do q @ (qx,(qy,qc)) <- mkQ xyc
applyU (urev (adder qx qy qc))
xyc <- measQ q
return xyc
tBiAdder :: (Int,(Int,Bool)) -> QIO (Int,(Int,Bool))
tBiAdder xyc = do
q @ (qx,(qy,qc)) <- mkQ xyc
applyU (adder qx qy qc)
applyU (urev (adder qx qy qc))
xyc <- measQ q
return xyc
adderMod :: Int -> QInt -> QInt -> U
adderMod n qa qb =
letU n (\ qn ->
letU False (\ qz ->
letU False (\ qc ->
adder qa qb qc
`mappend`
urev (adder qn qb qc)
`mappend`
cond qc (\ c -> if c then unot qz else mempty)
`mappend`
cond qz (\ z -> if z then adder qn qb qc else mempty)
`mappend`
urev (adder qa qb qc)
`mappend`
cond qc (\ c -> if c then mempty else unot qz)
`mappend`
adder qa qb qc)))
tadderMod :: Int -> (Int,Int) -> QIO (Int,Int)
tadderMod n ab = do q @ (qa,qb) <- mkQ ab
applyU (adderMod n qa qb)
ab <- measQ q
return ab
multMod :: Int -> Int -> QInt -> QInt -> U
multMod n a (QInt x) y = multMod' n a x y 1
where
multMod' _ _ [] _ _ = mempty
multMod' n a (x:xs) y p = cond x (\x -> (
if x then (letU ((p*a) `mod` n) (\ qa -> (adderMod n qa y)) `mappend` (multMod' n a xs y (p*2)))
else multMod' n a xs y (p*2)))
tmultMod :: Int -> Int -> Int -> QIO (Int,Int)
tmultMod n a x = do y <- mkQ 0
x' <- mkQ x
applyU(multMod n a x' y)
qy <- measQ y
qx <- measQ x'
return (qx,qy)
condMultMod :: Qbit -> Int -> Int -> QInt -> QInt -> U
condMultMod q n a x y = ifQ q (multMod n a x y)
inverseMod :: Int -> Int -> Int
inverseMod n a = case imods of
[] -> error ("inverseMod: no inverse of "++(show a)++" mod "++(show n)++ " found")
(x:_) -> x
where
imods = [x | x <- [1..n], ((x*a) `mod` n) == 1]
modExpStep :: Qbit -> Int -> Int -> QInt -> Int -> U
modExpStep qc n a o p = letU 0 (\z -> (condMultMod qc n p' o z)
`mappend` (ifQ qc (swapQInt o z))
`mappend` (urev (condMultMod qc n (inverseMod n p') o z)))
where
p' | (a^(2^p)) == 0 = error "modExpStep: arguments too large"
| otherwise = (a^(2^p)) `mod` n
modExpStept :: Int -> Int -> Int -> Int -> QIO Int
modExpStept i n a p = do
q <- mkQ True
one <- mkQ i
applyU (modExpStep q n a one p)
r <- measQ one
return r
modExp :: Int -> Int -> QInt -> QInt -> U
modExp n a (QInt x) o = modExp' n a x o 0
where
modExp' _ _ [] _ _ = mempty
modExp' n a (x:xs) o p = modExpStep x n a o p `mappend` (modExp' n a xs o (p+1))
modExpt :: Int -> (Int,Int) -> QIO Int
modExpt n (a,x) = do
qx <- mkQ x
one <- mkQ 1
applyU (modExp n a qx one)
r <- measQ one
return r