diff options
Diffstat (limited to 'testsuite/tests/concurrent/prog001/Stream.hs')
-rw-r--r-- | testsuite/tests/concurrent/prog001/Stream.hs | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/testsuite/tests/concurrent/prog001/Stream.hs b/testsuite/tests/concurrent/prog001/Stream.hs new file mode 100644 index 0000000000..349af32962 --- /dev/null +++ b/testsuite/tests/concurrent/prog001/Stream.hs @@ -0,0 +1,156 @@ +module Stream (Stream, carry, addStream, rationalToStream, + streamToFloat, addFiniteStream, negate', average) where + +import Data.Ratio + + +type Digit = Integer +type Stream = [Integer] + + + +-- Convert from a Rational fraction to its stream representation +rationalToStream :: Rational -> Stream +rationalToStream x + |t<1 = 0:rationalToStream t + |otherwise = 1:rationalToStream (t-1) + where t = 2*x + + + + +-- Convert from a stream to the Float value +streamToFloat :: Stream -> Float +streamToFloat x = f x (1) + +f :: Stream -> Integer -> Float +f [] n = 0 +f (y:ys) n = (fromIntegral)y/(fromIntegral(2^n)) + f ys (n+1) + + + + + +-- Add two stream +addStream :: Stream -> Stream -> Stream +addStream (x1:x2:x3:xs) (y1:y2:y3:ys) = (u+c):(addStream (x2:x3:xs) (y2:y3:ys)) + where u = interim x1 x2 y1 y2 + c = carry x2 x3 y2 y3 + + + +-- Compute carry, the C(i) value, given x(i) and y(i) +carry :: Digit -> Digit -> Digit -> Digit -> Digit +carry x1 x2 y1 y2 + |t>1 = 1 + |t<(-1) = -1 + |t==1 && (minus1 x2 y2) = 0 + |t==1 && not (minus1 x2 y2) = 1 + |t==(-1) && (minus1 x2 y2) = -1 + |t==(-1) && not (minus1 x2 y2) = 0 + |t==0 = 0 + where t = x1+y1 + + + +-- Computer the interim sum, the U(i) value, given x(i), y(i) and c(i) +interim :: Digit -> Digit -> Digit -> Digit -> Digit +interim x1 x2 y1 y2 + |t>1 = 0 + |t<(-1) = 0 + |t==1 && (minus1 x2 y2) = 1 + |t==1 && not (minus1 x2 y2) = -1 + |t==(-1) && (minus1 x2 y2) = 1 + |t==(-1) && not (minus1 x2 y2) = -1 + |t==0 = 0 + where t = x1+y1 + + + +-- Check if at least one of 2 digits is -1 +minus1 :: Digit -> Digit -> Bool +minus1 x y = (x==(-1))|| (y==(-1)) + + + + + + +-- Algin two stream so that they have the same length +align :: Stream -> Stream -> (Stream, Stream) +align xs ys + |x>y = (xs, (copy 0 (x-y)) ++ys) + |otherwise = ((copy 0 (y-x)) ++ xs, ys) + where x = toInteger(length xs) + y = toInteger(length ys) + + + +-- Generate a list of x +copy :: Integer -> Integer -> [Integer] +copy x n = [x| i<- [1..n]] + + + + + + + +-- Add two finite stream (to add the integral part) +addFiniteStream :: Stream -> Stream -> Stream +addFiniteStream xs ys = add' u v + where (u,v) = align xs ys + + + +-- Utility function for addFinitieStream +add' :: Stream -> Stream -> Stream +add' u v = normalise (f u v) + where f [] [] = [] + f (x:xs) (y:ys) = (x+y):f xs ys + + +-- Normalise the sum +normalise :: Stream -> Stream +normalise = foldr f [0] + where f x (y:ys) = (u:v:ys) + where u = (x+y) `div` 2 + v = (x+y) `mod` 2 + + +-- Negate a stream +negate' :: Stream -> Stream +negate' = map (*(-1)) + + + +-- Compute average of two stream +-- Using [-2,-1,0,1,2] to add, and then divide by 2 +average :: Stream -> Stream -> Stream +average xs ys = div2 (add xs ys) + + +-- Addition of two streams, using [-2,-1,0,1,2] +add :: Stream -> Stream -> Stream +add (x:xs) (y:ys) = (x+y):(add xs ys) + + +-- Then divided by 2, [-2,-1,0,1,2] -> [-1,0,1] +div2 :: Stream -> Stream +div2 (2:xs) = 1:div2 xs +div2 ((-2):xs) = (-1):div2 xs +div2 (0:xs) = 0:div2 xs +div2 (1:(-2):xs) = div2 (0:0:xs) +div2 (1:(-1):xs) = div2 (0:1:xs) +div2 (1:0:xs) = div2 (0:2:xs) +div2 (1:1:xs) = div2 (2:(-1):xs) +div2 (1:2:xs) = div2 (2:0:xs) +div2 ((-1):(-2):xs) = div2 ((-2):0:xs) +div2 ((-1):(-1):xs) = div2 ((-2):1:xs) +div2 ((-1):0:xs) = div2 (0:(-2):xs) +div2 ((-1):1:xs) = div2 (0:(-1):xs) +div2 ((-1):2:xs) = div2 (0:0:xs) + + + +test = take 100 (average (rationalToStream (1%2)) (rationalToStream (1%3))) |