summaryrefslogtreecommitdiff
path: root/testsuite/tests/concurrent/prog001/Stream.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/concurrent/prog001/Stream.hs')
-rw-r--r--testsuite/tests/concurrent/prog001/Stream.hs156
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)))