runKCM (LaunchUn blocks elems inf k outf i) ids km = result
  where 
    
    -- Generate kernel for lookup purposese
    kern = ((pure inputTransform ->- k ->- pOutput outf) (Array (\ix -> index "input0" ix) (fromIntegral elems)))
    inputTransform = \arr -> Array (\ix -> arr ! (inf ix)) (len arr)
    ((outArr,_),_) = runKernel kern
    (kernel,_,_) = CUDA.genKernel_ "gen" 
                             kern
                             [("input0",Int)]  -- type ??
                             [("output0",Int)] 
    
                             
    (newids,newkm,newprg) = 
      -- Has Kernel already been generated ? 
      case Map.lookup kernel km' of 
        Nothing -> 
          let id = snd ids'  
              -- Generate kernel again. with different name, for insertion. 
              -- (This should be improved upon) 
              kernelIns' =  CUDA.genKernel_ ("gen"  ++ show id)
                             kern
                             [("input0",Pointer Int)]  -- type ??
                             [("output0",Pointer Int)] 
              (str,threads,sm) = kernelIns'                     
              kernelIns = (str,"gen" ++ show id,threads, sm) -- TODO CLEANUP 
                              
          in  ((fst ids',id+1),Map.insert kernel kernelIns km', call ("gen" ++ show id) blocks threads sm (idOf res) (idOf newImm) ) --add one kernel 
        (Just (_,kernNom,threads,sm)) -> (ids',km',call kernNom blocks threads sm (idOf res) (idOf newImm)) --return excisting
     
 
     -- Generate the input to this stage  
    ((res,ids', km'),prg) = runKCM i ids km
    newImm = GlobalArray (fst newids)
    allocprg = allocImm newImm (fromIntegral (len outArr)*blocks) 
    
    result = ((newImm ,(fst newids +1,snd newids),newkm),allocprg ++ "\n"++ prg ++ " \n" ++ newprg ++ "\n")
runKCM (LaunchUn blocks elems inf k outf i) ids km = result
  where 
    
    -- Generate kernel for lookup purposese
    kern = ((pure inputTransform ->- k ->- pOutput outf) (Array (\ix -> index "input0" ix) (fromIntegral elems)))
    inputTransform = \arr -> Array (\ix -> arr ! (inf ix)) (len arr)
    ((outArr,_),_) = runKernel kern
    (kernel,_,_) = CUDA.genKernel_ "gen" 
                             kern
                             [("input0",Int)]  -- type ??
                             [("output0",Int)] 
    
                             
    (newids,newkm,newprg) = 
      -- Has Kernel already been generated ? 
      case Map.lookup kernel km' of 
        Nothing -> 
          let id = snd ids'  
              -- Generate kernel again. with different name, for insertion. 
              -- (This should be improved upon) 
              kernelIns' =  CUDA.genKernel_ ("gen"  ++ show id)
                             kern
                             [("input0",Pointer Int)]  -- type ??
                             [("output0",Pointer Int)] 
              (str,threads,sm) = kernelIns'                     
              kernelIns = (str,"gen" ++ show id,threads, sm) -- TODO CLEANUP 
                              
          in  ((fst ids',id+1),Map.insert kernel kernelIns km', call ("gen" ++ show id) blocks threads sm (idOf res) (idOf newImm) ) --add one kernel 
        (Just (_,kernNom,threads,sm)) -> (ids',km',call kernNom blocks threads sm (idOf res) (idOf newImm)) --return excisting
     
 
     -- Generate the input to this stage  
    ((res,ids', km'),prg) = runKCM i ids km
    newImm = GlobalArray (fst newids)
    allocprg = allocImm newImm (fromIntegral (len outArr)*blocks) 
    
    result = ((newImm ,(fst newids +1,snd newids),newkm),allocprg ++ "\n"++ prg ++ " \n" ++ newprg ++ "\n")
runKCM (LaunchUn blocks elems inf k outf i) ids km = result
  where 
    
    -- Generate kernel for lookup purposese
    kern = ((pure inputTransform ->- k ->- pOutput outf) (Array (\ix -> index "input0" ix) (fromIntegral elems)))
    inputTransform = \arr -> Array (\ix -> arr ! (inf ix)) (len arr)
    ((outArr,_),_) = runKernel kern
    (kernel,_,_) = CUDA.genKernel_ "gen" 
                             kern
                             [("input0",Int)]  -- type ??
                             [("output0",Int)] 
    
                             
    (newids,newkm,newprg) = 
      -- Has Kernel already been generated ? 
      case Map.lookup kernel km' of 
        Nothing -> 
          let id = snd ids'  
              -- Generate kernel again. with different name, for insertion. 
              -- (This should be improved upon) 
              kernelIns' =  CUDA.genKernel_ ("gen"  ++ show id)
                             kern
                             [("input0",Pointer Int)]  -- type ??
                             [("output0",Pointer Int)] 
              (str,threads,sm) = kernelIns'                     
              kernelIns = (str,"gen" ++ show id,threads, sm) -- TODO CLEANUP 
                              
          in  ((fst ids',id+1),Map.insert kernel kernelIns km', call ("gen" ++ show id) blocks threads sm (idOf res) (idOf newImm) ) --add one kernel 
        (Just (_,kernNom,threads,sm)) -> (ids',km',call kernNom blocks threads sm (idOf res) (idOf newImm)) --return excisting
     
 
     -- Generate the input to this stage  
    ((res,ids', km'),prg) = runKCM i ids km
    newImm = GlobalArray (fst newids)
    allocprg = allocImm newImm (fromIntegral (len outArr)*blocks) 
    
    result = ((newImm ,(fst newids +1,snd newids),newkm),allocprg ++ "\n"++ prg ++ " \n" ++ newprg ++ "\n")