content: module Trit (Trit, rationalToTrit, getIntegral, getFraction, getFraction',
                  neg, addTrits, subTrits, shiftLeft, shiftRight, multiply
                  ) where
  
  import Stream
  import Utilities
  import Data.Ratio
  
  type Mantissa = Stream
  type Fraction = Stream
  type Trit     = (Mantissa, Fraction)
  
  
  -- Convert from a Rational number to its Trit representation (Integral, Fraction)
  rationalToTrit :: Rational -> Trit
  rationalToTrit x
                  |x<1            = ([0], rationalToStream x)
                  |otherwise      = (u', rationalToStream v)
                  where   u = n `div` d
                          u' = toBinary u
                          v = x - (toRational u)
                          n = numerator x
                          d = denominator x
  
  
  -- Get the integral part of Trit
  getIntegral :: Trit -> Mantissa
  getIntegral = fst
  
  
  
  -- Get the fraction part of Trit, with n digit of the stream
  getFraction :: Int -> Trit -> Stream
  getFraction n = take n. snd
  
  
  -- Get the fraction part of Trit
  getFraction' :: Trit -> Stream
  getFraction' = snd
  
  
  
  -- Negate a Trit
  neg :: Trit -> Trit
  neg (a, b) = (negate' a, negate' b)
  
  
  
  -- Add two Trits
  addTrits :: Trit -> Trit -> Trit
  addTrits (m1, (x1:x2:xs)) (m2, (y1:y2:ys)) = (u,addStream (x1:x2:xs) (y1:y2:ys))
                                             where u' = addFiniteStream m1 m2
                                                   c = [carry x1 x2 y1 y2]
                                                   u = addFiniteStream u' c
  
  
  
  -- Substraction of 2 Trits
  subTrits :: Trit -> Trit -> Trit
  subTrits x y = addTrits x (neg y)
  
  
  
  -- Shift left = *2 opertaion with Trit
  shiftLeft :: Trit -> Trit
  shiftLeft (x, (y:ys)) = (x++ [y], ys)
  
  
  -- Shift right = /2 operation with Trit
  shiftRight :: Trit -> Integer -> Trit
  shiftRight (x, xs) 1 = (init x, (u:xs))
                      where u = last x
  shiftRight (x, xs) n = shiftRight (init x, (u:xs)) (n-1)
                      where u = last x
  
  
  
  -- Multiply a Trit stream by 1,0 or -1, simply return the stream
  mulOneDigit :: Integer -> Stream -> Stream
  mulOneDigit x xs
                |x==1      = xs
                |x==0      = zero'
                |otherwise = negate' xs
                where zero' = (0:zero')
  
  
  
  
  
  
  -- Multiplication of two streams
  multiply :: Stream -> Stream -> Stream
  multiply (a0:a1:x) (b0:b1:y) = average p q
                                 where p = average (a1*b0: (average (mulOneDigit b1 x)
                                                                   (mulOneDigit a1 y)))
                                                   (average (mulOneDigit b0 x)
                                                            (mulOneDigit a0 y))
                                       q = (a0*b0:a0*b1:a1*b1:(multiply x y))
  
  
  
  
  start0 = take 30 (multiply (rationalToStream (1%2)) zo)
  
  zo :: Stream
  zo = 1:(-1):zero
       where zero = 0:zero
  
  start1 = take 30 (average (rationalToStream (1%2)) (negate' (rationalToStream (1%4))))
  
  
  
  