content: 
  module Converter (rationalToGray, grayToSignIO, signToGray, Gray, startF, startC) where
  
  import Stream
  import Data.Ratio
  import Control.Concurrent
  import Control.Concurrent.MVar
  import System.IO.Unsafe
  
  
  type Gray = [Integer]
  type State = (Integer, Integer)
  
  
  -- Convert a rational number (in (-1,1)) to its Gray representation
  rationalToGray :: Rational -> Gray
  rationalToGray x
  		|x<0		= f (negate' (rationalToStream (-x))) (0,0)
  		|otherwise	= f (rationalToStream x) (0,0)
  		
  	
  -- Function to implement the two heads Turing machine that convert a
  -- signed-digit stream to the corresponding Gray-code representation		
  f :: Stream -> State -> Stream
  f (x:xs) (0,0)
  	    |x==(-1)	= 0:f xs (0,0)
  	    |x==0	= c:1:ds
  	    |x==1	= 1:f xs (1,0)
  	    where c:ds = f xs (0,1)
  	    
  f (x:xs) (0,1)
  	    |x==(-1)	= 0:f xs (1,0)
  	    |x==0	= c:0:ds
  	    |x==1	= 1:f xs (0,0)
  	    where c:ds = f xs (0,1)
  	    
  f (x:xs) (1,0)
  	    |x==(-1)	= 1:f xs (0,0)
  	    |x==0	= c:1:ds
  	    |x==1	= 0:f xs (1,0)
  	    where c:ds = f xs (1,1)
  	    
  f (x:xs) (1,1)
  	    |x==(-1)	= 1:f xs (1,0)
  	    |x==0	= c:0:ds
  	    |x==1	= 0:f xs (0,0)
  	    where c:ds = f xs (1,1)
  	  
  	  
  	  
  
  -- Anotherway to convert from a rational to Gray code representation
  -- Behave exactly the same like above	  
  rationalToGray' :: Rational -> Gray
  rationalToGray' x
  		|x<0		= signToGray (negate' (rationalToStream (-x)))	  
  	  	|otherwise	= signToGray (rationalToStream x) 
  		
  
  -- Function to convert a signed-digit stream to Gray representation
  -- Is much shorter than above		
  signToGray :: Stream -> Stream
  signToGray (1:xs) 	= 1:f'(signToGray xs)
  signToGray ((-1):xs) 	= 0:signToGray xs
  signToGray (0:xs) 	= c:1:(f' ds)
      		  	where c:ds = signToGray xs
  	    
  
  
  -- Convert a Gray-code stream to the corresponding signed-digit representation
  -- Make use of threads 	    
  grayToSignIO :: Stream -> IO Stream
  grayToSignIO (x1:x2:xs) = do
  			c <- threadTesting(x1:x2:xs)
  			if (c==1)
  			   then (do  co <- unsafeInterleaveIO (grayToSignIO (f'(x2:xs)))
  			             return (1:co))
  			   else if (c==2) 
  			   	   then (do co <- unsafeInterleaveIO (grayToSignIO (x2:xs))
  				            return ((-1):co))
                                     else (do co <- unsafeInterleaveIO (grayToSignIO (x1:f' xs))
  				            return (0:co))
  
  -- Flip the first bit of an infinite stream
  f' (x:xs) = (f'' x):xs
  	    where f'' 1 = 0
  	    	  f'' 0 = 1
  
  
  -- Launch two threads which run concurrently, test for the first digit of the stream (1, 0 or bottom)
  -- As soon as one thread terminate, grab that result and proceed
  threadTesting :: Stream -> IO Int
  threadTesting xs = do   m <- newEmptyMVar
  	    		c1 <- forkIO (f1 m xs)
  		    	c2 <- forkIO (f2 m xs)
  	    		c <- takeMVar m
  	    		killThread c1
  	    		killThread c2
  	    		return c
  	    
  -- Test case 1, when the first bit is either 1 or 0. 
  -- In case of bottom, f1 will never terminate, then f2 will definitely terminate	    
  f1 :: MVar Int -> Stream -> IO() 
  f1 m (0:xs) = putMVar m 2
  f1 m (1:xs) = putMVar m 1
  
  -- Test case 2, when the first bit is completely ignored, esp in case it was a bottom
  -- If the second bit is 1, then we can output, don't care value of the first bit
  -- If the second bit is 0, then loop forever, give chances to f1 to terminate
  f2 :: MVar Int -> Stream -> IO()
  f2 m (c1:c2:xs) 
  		|c2==1		= putMVar m 3
  		|otherwise	= yield
  
  
  
  
  -- Testing
  startC :: IO()
  startC = do
  	    c<- unsafeInterleaveIO (grayToSignIO (1:1:z0))
  	    putStrLn (show (take 100 c))
  
  
  startF = signToGray ((-1):1:z0)
  
  
  z0 = 0:z0
  loop' = loop'
  z1' = (1:z1')
  