[project @ 2001-02-21 12:55:48 by simonpj]
[ghc-hetmet.git] / glafp-utils / nofib-analyse / OptTable.hs
1 -----------------------------------------------------------------------------
2 -- $Id: OptTable.hs,v 1.2 2000/07/10 16:15:34 rrt Exp $
3 --
4 --      OGI_Table : Class for combinators used in building 2D tables.
5 --
6 --      Copyright (c) 1999 Andy Gill
7 --
8 -- This module is distributed as Open Source software under the
9 -- Artistic License; see the file "Artistic" that is included
10 -- in the distribution for details.
11 -----------------------------------------------------------------------------
12
13 module OptTable (
14         OptTable,               -- abstract
15         single,
16         beside,
17         above,
18         getMatrix,
19         ) where
20
21 import qualified ClassTable as TC
22
23 instance TC.Table OptTable where
24         single    = OptTable.single
25         beside    = OptTable.beside
26         above     = OptTable.above
27         getMatrix = OptTable.getMatrix
28
29 instance (Show a) => Show (OptTable a) where
30         showsPrec p = TC.showsTable
31
32 type TableI a = [[(a,(Int,Int))]] -> [[(a,(Int,Int))]]
33
34 data OptTable a = Table (Int -> Int -> TableI a) Int Int
35
36 {-
37  - Perhaps one day I'll fell adventureous, and write the Show instance
38  - to show boxes aka the above ascii renditions.
39  -}
40
41 -- You can create a (1x1) table entry
42 single :: a -> OptTable a
43 single a = Table (\ x y z -> [(a,(x+1,y+1))] : z) 1 1
44
45 -- You can compose tables, horizonally and vertically
46 above :: OptTable a -> OptTable a -> OptTable a
47 beside :: OptTable a -> OptTable a -> OptTable a
48
49 t1 `above` t2 = trans (combine (trans t1) (trans t2) (.))
50
51 t1 `beside` t2 = combine t1 t2 (\ lst1 lst2 r ->
52     let
53         -- Note this depends on the fact that
54         -- that the result has the same number
55         -- of lines as the y dimention; one list
56         -- per line. This is not true in general
57         -- but is always true for these combinators.
58         -- I should assert this!
59         beside (x:xs) (y:ys) = (x ++ y) : beside xs ys
60         beside (x:xs) []     = x        : xs ++ r
61         beside []     (y:ys) = y        : ys ++ r
62         beside []     []     =                  r
63     in
64         beside (lst1 []) (lst2 []))
65
66 -- trans flips (transposes) over the x and y axis of
67 -- the table. It is only used internally, and typically
68 -- in pairs, ie. (flip ... munge ... (un)flip).
69
70 trans :: OptTable a -> OptTable a
71 trans (Table f1 x1 y1) = Table (flip f1) y1 x1
72
73 combine :: OptTable a 
74         -> OptTable b 
75         -> (TableI a -> TableI b -> TableI c) 
76         -> OptTable c
77 combine (Table f1 x1 y1) (Table f2 x2 y2) comb = Table new_fn (x1+x2) max_y
78     where
79         max_y = max y1 y2
80         new_fn x y =
81            case compare y1 y2 of
82             EQ -> comb (f1 0 y)             (f2 x y)
83             GT -> comb (f1 0 y)             (f2 x (y + y1 - y2))
84             LT -> comb (f1 0 (y + y2 - y1)) (f2 x y)
85
86 -- This is the other thing you can do with a Table;
87 -- turn it into a 2D list, tagged with the (x,y)
88 -- sizes of each cell in the table.
89
90 getMatrix :: OptTable a -> [[(a,(Int,Int))]]
91 getMatrix (Table r _ _) = r 0 0 []
92