Trying to limit some of the instructions we do in Karatsuba multiplication ...

This commit is contained in:
2020-04-26 19:53:40 -07:00
parent 9ee668daad
commit a622aa9cc9

View File

@@ -6,9 +6,12 @@
{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE TypeSynonymInstances #-}
module Karatsuba( module Karatsuba(
Instruction(..) Instruction(..)
, InstructionData(..)
, Variable
, runChecks , runChecks
, runQuickCheck , runQuickCheck
, generateInstructions , generateInstructions
, variableName
) )
where where
@@ -20,31 +23,37 @@ import Data.LargeWord
import Data.List import Data.List
import Data.Map.Strict(Map) import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.Vector(Vector, (!?)) import Data.Vector(Vector)
import qualified Data.Vector as V import qualified Data.Vector as V
import Data.Word import Data.Word
import Debug.Trace
import Prelude hiding (fail) import Prelude hiding (fail)
import Test.QuickCheck hiding ((.&.)) import Test.QuickCheck hiding ((.&.))
import Debug.Trace
-- this drives the testing -- this drives the testing
inputWordSize :: Int inputWordSize :: Int
inputWordSize = 5 inputWordSize = 5
generateInstructions :: Word -> [Instruction] data InstructionData = InstructionData {
generateInstructions numdigits = idInstructions :: [Instruction],
let (baseVec, baseInstrs) = runMath $ do x <- V.replicateM (fromIntegral numdigits) (genDigit 1) idInput1 :: [Variable],
y <- V.replicateM (fromIntegral numdigits) (genDigit 1) idInput2 :: [Variable],
karatsuba x y idOutput :: [Variable]
in baseInstrs }
-- foldl replaceVar baseInstrs varRenames generateInstructions :: Word -> InstructionData
-- where generateInstructions numdigits =
-- x = rename "x" (V.replicate (fromIntegral numdigits) (D "" 1)) let (baseID, baseInstrs) = runMath $ do (x, xinstrs) <- listen $ V.replicateM (fromIntegral numdigits) (genDigit 1)
-- y = rename "y" (V.replicate (fromIntegral numdigits) (D "" 1)) (y, yinstrs) <- listen $ V.replicateM (fromIntegral numdigits) (genDigit 1)
-- (baseVec, baseInstrs) = runMath (karatsuba x y) res <- karatsuba x y
-- res = rename "res" baseVec return InstructionData {
-- varRenames = zip (map name (V.toList baseVec)) (map name (V.toList res)) idInstructions = xinstrs ++ yinstrs,
idInput1 = map name (V.toList x),
idInput2 = map name (V.toList y),
idOutput = map name (V.toList res)
}
(preps, reals) = splitAt (length (idInstructions baseID)) baseInstrs
in baseID{ idInstructions = preps ++ simplifyConstants reals }
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- --
@@ -56,6 +65,9 @@ generateInstructions numdigits =
newtype Variable = V Word newtype Variable = V Word
deriving (Eq, Ord, Show) deriving (Eq, Ord, Show)
variableName :: Variable -> String
variableName (V x) = "t" ++ show x
-- these are in Intel form, as I was corrupted young, so the first argument -- these are in Intel form, as I was corrupted young, so the first argument
-- is the destination and the rest are the arguments. -- is the destination and the rest are the arguments.
data Instruction = Add Variable [Variable] data Instruction = Add Variable [Variable]
@@ -113,22 +125,48 @@ run env instrs =
[] -> env [] -> env
(x:rest) -> run (step env x) rest (x:rest) -> run (step env x) rest
replaceVar :: [Instruction] -> (Variable, Variable) -> [Instruction] simplifyConstants :: [Instruction] -> [Instruction]
replaceVar ls (from, to) = map replace ls simplifyConstants instrs = go instrs Map.empty Map.empty Map.empty
where where
replace x = go [] _ _ _ = []
case x of go (instr:rest) consts64 consts128 remaps =
Add outname items -> Add (sub outname) (map sub items) case instr of
CastDown outname item -> CastDown (sub outname) (sub item) Add outname items ->
CastUp outname item -> CastUp (sub outname) (sub item) Add outname (map (replace remaps) items) : go rest consts64 consts128 remaps
Complement outname item -> Complement (sub outname) (sub item)
Declare64 outname val -> Declare64 (sub outname) val CastDown outname item ->
Declare128 outname val -> Declare128 (sub outname) val CastDown outname (replace remaps item) : go rest consts64 consts128 remaps
Mask outname item mask -> Mask (sub outname) (sub item) mask
Multiply outname items -> Multiply (sub outname) (map sub items) CastUp outname item ->
ShiftR outname item amt -> ShiftR (sub outname) (sub item) amt CastUp outname (replace remaps item) : go rest consts64 consts128 remaps
sub x | x == from = to
| otherwise = x Complement outname item ->
Complement outname (replace remaps item) : go rest consts64 consts128 remaps
Declare64 outname val | Just outname' <- Map.lookup val consts64 ->
go rest consts64 consts128 (Map.insert outname outname' remaps)
Declare64 outname val ->
Declare64 outname val : go rest (Map.insert val outname consts64) consts128 remaps
Declare128 outname val | Just outname' <- Map.lookup val consts128 ->
go rest consts64 consts128 (Map.insert outname outname' remaps)
Declare128 outname val ->
Declare128 outname val : go rest consts64 (Map.insert val outname consts128) remaps
Mask outname item mask ->
Mask outname (replace remaps item) mask : go rest consts64 consts128 remaps
Multiply outname items ->
Multiply outname (map (replace remaps) items) : go rest consts64 consts128 remaps
ShiftR outname item amt ->
ShiftR outname (replace remaps item) amt : go rest consts64 consts128 remaps
replace :: Map Variable Variable -> Variable -> Variable
replace remaps item = Map.findWithDefault item item remaps
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- --
@@ -593,14 +631,19 @@ prop_KaratsubaWorks l x y =
y' = abs y `mod` (2 ^ (64 * l')) y' = abs y `mod` (2 ^ (64 * l'))
prop_InstructionsWork :: Int -> Integer -> Integer -> Bool prop_InstructionsWork' ::
prop_InstructionsWork l x y = ([Instruction] -> [Instruction]) ->
Int ->
Integer ->
Integer ->
Bool
prop_InstructionsWork' f l x y =
let (value, instructions) = runMath $ do numx <- convertTo l' x' let (value, instructions) = runMath $ do numx <- convertTo l' x'
numy <- convertTo l' y' numy <- convertTo l' y'
karatsuba numx numy karatsuba numx numy
resGMP = x' * y' resGMP = x' * y'
resKaratsuba = convertFrom value resKaratsuba = convertFrom value
(endEnvironment, _) = run (Map.empty, Map.empty) instructions (endEnvironment, _) = run (Map.empty, Map.empty) (f instructions)
instrVersion = V.map (getv endEnvironment . name) value instrVersion = V.map (getv endEnvironment . name) value
in (resGMP == resKaratsuba) && (value == instrVersion) in (resGMP == resKaratsuba) && (value == instrVersion)
where where
@@ -612,6 +655,12 @@ prop_InstructionsWork l x y =
Nothing -> error ("InstrProp lookup failure: " ++ show n) Nothing -> error ("InstrProp lookup failure: " ++ show n)
Just v -> D n v Just v -> D n v
prop_InstructionsWork :: Int -> Integer -> Integer -> Bool
prop_InstructionsWork = prop_InstructionsWork' id
prop_SimplifiedInstructionsWork :: Int -> Integer -> Integer -> Bool
prop_SimplifiedInstructionsWork = prop_InstructionsWork' simplifyConstants
prop_InstructionsConsistent :: Int -> Integer -> Integer -> Integer -> Integer -> Bool prop_InstructionsConsistent :: Int -> Integer -> Integer -> Integer -> Integer -> Bool
prop_InstructionsConsistent l a b x y = prop_InstructionsConsistent l a b x y =
let (_, instrs1) = runMath (karatsuba' a' b') let (_, instrs1) = runMath (karatsuba' a' b')
@@ -647,16 +696,17 @@ runQuickCheck testname prop =
runChecks :: IO () runChecks :: IO ()
runChecks = runChecks =
do runQuickCheck "Int -> Num -> Int " prop_ConversionWorksInt do runQuickCheck "Int -> Num -> Int " prop_ConversionWorksInt
runQuickCheck "Split Isn't Dumb " prop_SplitDigitsIsntTerrible runQuickCheck "Split Isn't Dumb " prop_SplitDigitsIsntTerrible
runQuickCheck "More 0s is Shift " prop_AddZerosIsShift runQuickCheck "More 0s is Shift " prop_AddZerosIsShift
runQuickCheck "PadTo Does That " prop_PadToWorks runQuickCheck "PadTo Does That " prop_PadToWorks
runQuickCheck "Add2 Works " prop_Add2Works runQuickCheck "Add2 Works " prop_Add2Works
runQuickCheck "Add3 Works " prop_Add3Works runQuickCheck "Add3 Works " prop_Add3Works
runQuickCheck "Sub2 Works " prop_Sub2Works runQuickCheck "Sub2 Works " prop_Sub2Works
runQuickCheck "Mul1 Works " prop_Mul1Works runQuickCheck "Mul1 Works " prop_Mul1Works
runQuickCheck "Mul2 Works " prop_Mul2Works runQuickCheck "Mul2 Works " prop_Mul2Works
runQuickCheck "Mul3 Works " prop_Mul3Works runQuickCheck "Mul3 Works " prop_Mul3Works
runQuickCheck "Karatsuba Works " prop_KaratsubaWorks runQuickCheck "Karatsuba Works " prop_KaratsubaWorks
runQuickCheck "Instructions Work " prop_InstructionsWork runQuickCheck "Instructions Work " prop_InstructionsWork
runQuickCheck "Generation Consistent " prop_InstructionsConsistent runQuickCheck "Simpl. Instructions Work " prop_SimplifiedInstructionsWork
runQuickCheck "Generation Consistent " prop_InstructionsConsistent