# LANGUAGE ForeignFunctionInterface #
  module  where

import Criterion.Main
import MatMul
import Endoscope
import Data.Bits
import Data.List
import qualified Data.Map as Map

import Foreign
import Foreign.C.Types


import qualified Data.Vector.Storable as V
import qualified Data.Vector.Storable.Mutable as VM


-- foreign import ccall unsafe "domultpacked"
--      c_mult_packed :: Int -> IO ()

-- foreign import ccall unsafe "domultunpacked"
--      c_mult_unpacked :: Int -> IO ()

-- foreign import ccall unsafe "matrix_mul_gf2"
--      c_mulgf2 :: Ptr a -> Ptr b -> Ptr c -> IO ()

-- foreign import ccall unsafe "matmul_basicgf2"
--      c_mulgf2basic ::  Ptr a -> Ptr b -> Ptr c -> IO ()

  foreign import ccall safe " setfront "
        : : Ptr a - >  > IO ( )
-- doset  a = do
--  let vs = V.fromList ([1,2,3] :: [CInt])
--  v <- V.thaw vs
   VM.unsafeWith v $ \ptr - > do
      setfront ptr 23
--  out <- V.freeze v
--  print out

-- do_cpacked a = c_mult_packed

-- do_cunpacked a = c_mult_unpacked


-- import qualified Data.Set as Set

--toPacked :: [[a]] -> [Int]
-- toPacked rows = map packRow rows
      
  packRow x = sum $ map shiftTup   $ zip x [ 0 .. ]
-- shiftTup (a,b) = shift a b

-- toPackedTup a = (toPacked a, toPacked $ transpose a)

       
-- packedMats x = map toPackedTup $ matsZ2 x


  packedRowMult   = ( . & . ) 1 $ popCount $ ( . & . )  

-- -- Recheck these vals....
  -- transpose A*B = transpose B * transpose A    
  packedTupMult ( ar , art ) ( br ,  ) = ( toPacked $ [ [ packedRowMult a b   | b < - brt ] | a < - ar ] ,
        toPacked $ [ [ packedRowMult a b   | b < - art ] | a < - br ] )



takeNum = 5000

matList3 = matsZ2 3
cProd elts mf =  [ mf x y | x <- elts, y <- elts]

regmult x = length $ cProd (take takeNum (matsZ2 x)) mmult

imult x = length $ cProd [0..(takeNum)] (+)

  = length $ cProd ( take takeNum $ packedMats x ) 


constructMultMap elts mult = Map.fromList $ multMapList elts mult

--multByMap a b theMap = (Map.!) theMap (a,b)


mapMatMulCart x = length $ cProd (take takeNum (matsZ2 x)) mymult
                  where
                    theMap = Map.fromList $ multMapList (matsZ2 x)  mmult
                    mymult x y = (Map.!) theMap (x,y)

mapMatMul x =  endoscope (matsZ2 x) mymult
              where
                theMap = Map.fromList $ multMapList (matsZ2 x)  mmult
                mymult x y = (Map.!) theMap (x,y)


-- Our benchmark harness.
main =
       defaultMain [
  bgroup " cmult " [ bench " packed " $ whnf do_cpacked 3
    , bench " unpacked " $ whnf do_cunpacked 3
    , bench " doset " $ whnf doset 3 ] ,
       bgroup "map matmul" [ bench "3" $ whnf mapMatMul 3],

       bgroup "intmul" [ bench "3" $ whnf imult 3],
       bgroup "map matmulCart" [ bench "3" $ whnf mapMatMulCart  3],
       bgroup "matmul" [ bench "3" $ whnf regmult 3 ]
  bgroup "  " [ bench " 3 " $ whnf pmult 3
  -- , bench " 4 " $ whnf pmult 4
       -- ]
               --,

  bgroup " trans endoscope " [ bench " 2 " $ whnf endoTransThing 2 ,
            bench " 3 " $ whnf endoTransThing 3
            , bench " 4 " $ whnf endoTransThing 4
       --         ],
  bgroup " perm endoscope " [ bench " 2 " $ whnf endoPermThing 2 ,
            bench " 3 " $ whnf endoPermThing 3
            , bench " 4 " $ whnf endoPermThing 4
       --         ]


  ]

 foreign import ccall unsafe "domultpacked"
      c_mult_packed :: Int -> IO ()
 foreign import ccall unsafe "domultunpacked"
      c_mult_unpacked :: Int -> IO ()
 foreign import ccall unsafe "matrix_mul_gf2"
      c_mulgf2 :: Ptr a -> Ptr b -> Ptr c -> IO ()
 foreign import ccall unsafe "matmul_basicgf2"
      c_mulgf2basic ::  Ptr a -> Ptr b -> Ptr c -> IO ()
 doset  a = do
  let vs = V.fromList ([1,2,3] :: [CInt])
  v <- V.thaw vs
  out <- V.freeze v
  print out
 do_cpacked a = c_mult_packed
 do_cunpacked a = c_mult_unpacked
 import qualified Data.Set as Set
toPacked :: [[a]] -> [Int]
 toPacked rows = map packRow rows
 shiftTup (a,b) = shift a b
 toPackedTup a = (toPacked a, toPacked $ transpose a)
 packedMats x = map toPackedTup $ matsZ2 x
 -- Recheck these vals....
 transpose A*B = transpose B * transpose A    
multByMap a b theMap = (Map.!) theMap (a,b)
 Our benchmark harness.
 , bench " 4 " $ whnf pmult 4
 ]
,
         ],
         ]
# LANGUAGE ForeignFunctionInterface #
  module  where

import Criterion.Main
import MatMul
import Endoscope
import Data.Bits
import Data.List
import qualified Data.Map as Map

import Foreign
import Foreign.C.Types


import qualified Data.Vector.Storable as V
import qualified Data.Vector.Storable.Mutable as VM






  foreign import ccall safe " setfront "
        : : Ptr a - >  > IO ( )
   VM.unsafeWith v $ \ptr - > do
      setfront ptr 23





      
  packRow x = sum $ map shiftTup   $ zip x [ 0 .. ]


       


  packedRowMult   = ( . & . ) 1 $ popCount $ ( . & . )  

  packedTupMult ( ar , art ) ( br ,  ) = ( toPacked $ [ [ packedRowMult a b   | b < - brt ] | a < - ar ] ,
        toPacked $ [ [ packedRowMult a b   | b < - art ] | a < - br ] )



takeNum = 5000

matList3 = matsZ2 3
cProd elts mf =  [ mf x y | x <- elts, y <- elts]

regmult x = length $ cProd (take takeNum (matsZ2 x)) mmult

imult x = length $ cProd [0..(takeNum)] (+)

  = length $ cProd ( take takeNum $ packedMats x ) 


constructMultMap elts mult = Map.fromList $ multMapList elts mult



mapMatMulCart x = length $ cProd (take takeNum (matsZ2 x)) mymult
                  where
                    theMap = Map.fromList $ multMapList (matsZ2 x)  mmult
                    mymult x y = (Map.!) theMap (x,y)

mapMatMul x =  endoscope (matsZ2 x) mymult
              where
                theMap = Map.fromList $ multMapList (matsZ2 x)  mmult
                mymult x y = (Map.!) theMap (x,y)


main =
       defaultMain [
  bgroup " cmult " [ bench " packed " $ whnf do_cpacked 3
    , bench " unpacked " $ whnf do_cunpacked 3
    , bench " doset " $ whnf doset 3 ] ,
       bgroup "map matmul" [ bench "3" $ whnf mapMatMul 3],

       bgroup "intmul" [ bench "3" $ whnf imult 3],
       bgroup "map matmulCart" [ bench "3" $ whnf mapMatMulCart  3],
       bgroup "matmul" [ bench "3" $ whnf regmult 3 ]
  bgroup "  " [ bench " 3 " $ whnf pmult 3

  bgroup " trans endoscope " [ bench " 2 " $ whnf endoTransThing 2 ,
            bench " 3 " $ whnf endoTransThing 3
            , bench " 4 " $ whnf endoTransThing 4
  bgroup " perm endoscope " [ bench " 2 " $ whnf endoPermThing 2 ,
            bench " 3 " $ whnf endoPermThing 3
            , bench " 4 " $ whnf endoPermThing 4


  ]
