id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc
27	Space leak in to2sComplement	dom	somebody	"The space leak is actually in to2scomplement. The culprit is reverse -
obvious once you think about it. 2^(106) used to almost destroy my
machine and anything bigger actually did grind it to a complete standstill.

> > to2sComplement :: Num a => Integer -> [a]
> > to2sComplement n
> >    | n >= 0 = 0:(k 7 n)
> >    | otherwise = k 8 (fromInteger $ 2^p + n)
> >    where
> >       p = length (k 7 (-n-1)) + 1
> > 
> > infixr 5 $$
> > ($$) = (.).(.)
> > 
> > k :: Num a => Integer -> Integer -> [a]
> > k = reverse $$ (map fromInteger) $$ flip (curry (unfoldr nnbIterator)) 
> > 
> > nnbIterator :: (Integer, Integer) -> Maybe (Integer, (Integer, Integer))
> > nnbIterator (0,0) = Nothing
> > nnbIterator (0,p) = Just (0,(0,p-1))
> > nnbIterator (n,0) = Just (n `rem` 2,(n `quot` 2,7))
> > nnbIterator (n,p) = Just (n `rem` 2,(n `quot` 2,p-1))


OTOH this seems to run in log space (which you might expect) consuming
about 200k for 2^(106) (a 300k digit number) which doesn't seem
unreasonable.

This puts more emphasis on changing to use the BitPut monad. I think it
should be straightforward to make the change now everything is monadic.
I'll have a look at what's involved but first I want to get the
inter-operability testing framework working.

> > h' :: Integer -> Integer -> BitPut
> > h' p 0 =
> >    do putNBits (fromIntegral p) (0::Word8)
> > h' 0 n =
> >    do putNBits 1 (n `mod` 2)
> >       h' 7 (n `div` 2)
> > h' p n =
> >    do putNBits 1 (n `mod` 2)
> >       h' (p-1) (n `div` 2)
> >   
> > to2sComplementReverse :: Integer -> BitPut
> > to2sComplementReverse n
> >    | n >= 0 = do h' 7 n
> >                  putNBits 1 (0::Word8)
> >    | otherwise = h' 8 (2^(l n) + n)
> > 
> > l n = genericLength ((flip (curry (unfoldr nnbIterator)) 7) (-n-1)) + 1
> > 
> > to2sComplementUsingReverse :: Integer -> BL.ByteString
> > to2sComplementUsingReverse n =
> >    BL.reverse (BL.map reverseBits (runBitPut (to2sComplementReverse n)))

> > reverseBits :: Word8 -> Word8
> > reverseBits = reverseBits3 . reverseBits2 . reverseBits1
> > 
> > reverseBits1 :: Word8 -> Word8
> > reverseBits1 x = shiftR x 4 .|. shiftL x 4
> > 
> > reverseBits2 :: Word8 -> Word8
> > reverseBits2 x = shiftR (x .&. 0xcc) 2 .|. shiftL (x .&. 0x33) 2
> > 
> > reverseBits3 :: Word8 -> Word8
> > reverseBits3 x = shiftR (x .&. 0xaa) 1 .|. shiftL (x .&. 0x55) 1
"	defect	new	major		component1				
