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