{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Algorithms/QLS/QSignedInt.hs" #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Quipper.Algorithms.QLS.QSignedInt where
import Data.Typeable
import Quipper
import Quipper.Internal
import Quipper.Libraries.Arith
import Quipper.Libraries.Simulation
import Quipper.Algorithms.QLS.Utils
import Quipper.Algorithms.QLS.QSignedIntAux
import Quipper.Utils.Auxiliary
data SignedInt x = SInt [x] x
deriving (Show, Typeable)
type FSignedInt = SignedInt Bool
type QSignedInt = SignedInt Qubit
type CSignedInt = SignedInt Bit
fsint_of_integer :: Int -> Integer -> FSignedInt
fsint_of_integer m x = SInt digits sign where
digits = boollist_of_int_bh m (abs x)
sign = (x < 0)
integer_of_fsint :: FSignedInt -> Integer
integer_of_fsint (SInt digits sign) = if sign then -a else a where
a = int_of_boollist_unsigned_bh digits
sint_length :: SignedInt x -> Int
sint_length (SInt digits sign) = length digits
instance Enum FSignedInt where
succ x = fsint_of_integer m . succ . integer_of_fsint $ x
where m = sint_length x
pred x = fsint_of_integer m . pred . integer_of_fsint $ x
where m = sint_length x
toEnum x = fsint_of_integer m (fromIntegral x)
where m = (+) 1 $ ceiling $ logBase 2 $ fromIntegral x
fromEnum x = fromIntegral . integer_of_fsint $ x
type instance QCType x y (SignedInt z) = SignedInt (QCType x y z)
type instance QTypeB FSignedInt = QSignedInt
instance QCLeaf x => QCData (SignedInt x) where
qcdata_mapM (shape :: SignedInt x) f g (SInt digits sign) = do
digits' <- qcdata_mapM [dummy :: x] f g digits
sign' <- qcdata_mapM (dummy :: x) f g sign
return (SInt digits' sign')
qcdata_zip (shape :: SignedInt x) q c q' c' (SInt digits sign) (SInt digits' sign') e
= (SInt digits'' sign'')
where
digits'' = qcdata_zip [dummy :: x] q c q' c' digits digits' errmsg
sign'' = qcdata_zip (dummy :: x) q c q' c' sign sign' e
errmsg x = e "SignedInt length mismatch"
qcdata_promote (SInt digits sign) (SInt digits' sign') e
| length digits /= length digits'
= error (e "SignedInt length mismatch")
| otherwise
= (SInt digits'' sign'')
where
digits'' = qcdata_promote digits digits' e
sign'' = sign
instance QCLeaf x => Labelable (SignedInt x) String where
label_rec (SInt digits sign) s = do
label_rec (reverse digits) s
label_rec sign s `dotted_indexed` "sign"
left_pad_qulist :: [Qubit] -> [Qubit] -> Circ ([Qubit],[Qubit])
left_pad_qulist l1 l2 = if (length l1 == length l2) then return (l1,l2)
else do
let m = abs (length l1 - length l2)
pad <- qinit (replicate m False)
if (length l1 > length l2)
then return (l1,pad ++ l2)
else return (pad ++ l1, l2)
fsint_shift :: Int -> FSignedInt -> FSignedInt
fsint_shift k (SInt digits sign) = (SInt digits' sign)
where
digits' = digits ++ replicate k False
s_qdint_of_qsint :: QSignedInt -> (Qubit, QDInt)
s_qdint_of_qsint (SInt q b) = (b, qdint_of_qulist_bh q)
qsint_of_s_qdint :: (Qubit, QDInt) -> QSignedInt
qsint_of_s_qdint (b, q) = SInt (qulist_of_qdint_bh q) b
qsint_shift :: Int -> QSignedInt -> Circ QSignedInt
qsint_shift k (SInt digits sign) = do
pad <- qinit (replicate k False)
let digits' = digits ++ pad
return (SInt digits' sign)
instance QOrd QSignedInt where
q_less (SInt x' b) (SInt y' c) = do
(x,y) <- left_pad_qulist x' y'
unpack template_be_signed_boollist_less (b, x) (c, y)
instance Eq FSignedInt where
x == y = (integer_of_fsint x) == (integer_of_fsint y)
instance Ord FSignedInt where
compare x y = compare (integer_of_fsint x) (integer_of_fsint y)
instance Num FSignedInt where
x + y = fsint_of_integer m $ (integer_of_fsint x) + (integer_of_fsint y)
where
m = max (sint_length x) (sint_length y)
x * y = fsint_of_integer m $ (integer_of_fsint x) * (integer_of_fsint y)
where
m = max (sint_length x) (sint_length y)
x - y = fsint_of_integer m $ (integer_of_fsint x) - (integer_of_fsint y)
where
m = max (sint_length x) (sint_length y)
fromInteger x = fsint_of_integer fixed_int_register_length x
abs x = fsint_of_integer m . abs . integer_of_fsint $ x
where
m = sint_length x
signum x = fsint_of_integer m . signum . integer_of_fsint $ x
where
m = sint_length x
instance Real FSignedInt where
toRational = toRational . integer_of_fsint
instance Integral FSignedInt where
quotRem x y = (fsint_of_integer m q, fsint_of_integer m r) where
m = max (sint_length x) (sint_length y)
(q,r) = quotRem (integer_of_fsint x) (integer_of_fsint y)
toInteger = integer_of_fsint
instance QNum QSignedInt where
q_add (SInt x' b) (SInt y' c) = do
(x,y) <- left_pad_qulist x' y'
(d,z) <- unpack template_be_signed_boollist_add (b,x) (c,y)
return (SInt x' b, SInt y' c, SInt z d)
q_mult (SInt x' b) (SInt y' c) = do
(x,y) <- left_pad_qulist x' y'
(_, _, z') <- q_mult (qdint_of_qulist_bh x) (qdint_of_qulist_bh y)
(_, _, d') <- q_add (qdint_of_qulist_bh [b]) (qdint_of_qulist_bh [c])
let z = qulist_of_qdint_bh z'
let d = qulist_of_qdint_bh d'
return (SInt x' b, SInt y' c, SInt z $ head d)
q_sub x y = do
(y,z) <- q_negate y
(x,z,t) <- q_add x z
return (x,y,t)
q_abs (SInt l s) = do
l' <- qinit $ qc_false l;
s' <- qinit False
controlled_not_at l' l
return (SInt l s, SInt l' s')
q_negate (SInt l s) = do
l' <- qinit $ qc_false l;
s' <- qinit False
controlled_not_at l' l
qnot_at s' `controlled` s .==. 0
return (SInt l s, SInt l' s')
q_signum (SInt l s) = do
l' <- qinit $ qc_false l;
s' <- qinit False
qnot s' `controlled` s
return (SInt l s, SInt l' s')
q_fromQDInt l1 = do
let l = qulist_of_qdint_bh l1
l' <- qinit $ qc_false l;
controlled_not_at l' l
s' <- qinit False
return (qdint_of_qulist_bh l, SInt l' s')
q_mod :: QSignedInt -> QSignedInt -> Circ QSignedInt
q_mod x y = do
let (x_b, x') = s_qdint_of_qsint x
let (y_b, y') = s_qdint_of_qsint y
(_,_,z1) <- q_quot x' y'
(_,_,z2) <- q_mult y' z1
(_,_,z3) <- q_sub x' z2
z_b <- qinit False
qnot_at z_b `controlled` x_b
qnot_at z_b `controlled` y_b
let z = qsint_of_s_qdint (z_b,z3)
return z
my_test = let x = fsint_of_integer 50 1595713 in
let y = fsint_of_integer 30 547137 in
let last (x,y,z) = z in
do
putStrLn $ show (x < y)
putStrLn $ show $ last $ run_classical_generic q_add x y
putStrLn $ show (x - y)
putStrLn $ show $ last $ run_classical_generic q_sub x y
putStrLn $ show $ run_classical_generic q_less x y
putStrLn $ show $ run_classical_generic q_less y x
print_simple GateCount $ do
a <- qinit x
b <- qinit y
b <- q_less a b
return ()