1 module Memo(Triangle,mkmemo,lazyAbove) where
    2 import Numbers
    3 import Vectors
    4 import EdgePlate
    5 import Comparing(above)
    6 import Ix
    7 import Array
    8 
    9 data Triangle a = a :^ a deriving (Eq,Ord, {-1.3-}Show)
   10 
   11 instance (Enum a,Ord a,Ix a) => Ix (Triangle a) where
   12         range (t0 :^ b0 , t1 :^ b1) =
   13                 [t :^ b | t <- [t0 .. t1]
   14                         , b <- take (1+index(t0,t1) t) [b0 .. ]
   15                         , t :^ b <= t1 :^ b1
   16                 ]
   17         index (t0 :^ b0 , t1 :^ b1) (t :^ b) =
   18                 ti * (ti+1) `div` 2 + index (b0,b1) b
   19                 where ti = index (t0,t1) t
   20         inRange (t0 :^ b0 , t1 :^ b1) (t :^ b) =
   21                 inRange (t0,t1) t &&
   22                 inRange (b0,b1) b && index (t0,t1) t >= index (b0,b1) b
   23 
   24 mkmemo :: (Plate -> Plate -> a) -> Object -> Array (Triangle Int) a
   25 mkmemo f obj =
   26         array (2:^1 , len:^(len-1)) [((top:^bottom) , f ls ks)
   27                                     |ls@(Plt top _) <- obj
   28                                     ,ks@(Plt bottom _) <- obj
   29                                     ,top > bottom]
   30         where len = length obj
   31 
   32 
   33 lazyAbove :: Array (Triangle Int) Bool -> Plate -> Plate -> Bool
   34 lazyAbove memory top@(Plt n _) bottom@(Plt m _)
   35         | inRange (bounds memory) (n :^ m) = memory ! (n:^m)
   36         | n==m                         = False
   37         | otherwise            = if memory ! (m:^n)
   38                                              then False
   39                                              else top`above`bottom