| 1 | 2 patches for repository /home/dafis/Haskell/Hacking/ghc/libraries/integer-gmp: |
|---|
| 2 | |
|---|
| 3 | Wed Mar 30 18:18:52 CEST 2011 Daniel Fischer <daniel.is.fischer@googlemail.com> |
|---|
| 4 | * Integer logarithms |
|---|
| 5 | Added modules for fast calculation of integer logarithms needed for fromRational. |
|---|
| 6 | |
|---|
| 7 | Thu Mar 31 01:17:10 CEST 2011 Daniel Fischer <daniel.is.fischer@googlemail.com> |
|---|
| 8 | * Fix Haddock markup |
|---|
| 9 | |
|---|
| 10 | New patches: |
|---|
| 11 | |
|---|
| 12 | [Integer logarithms |
|---|
| 13 | Daniel Fischer <daniel.is.fischer@googlemail.com>**20110330161852 |
|---|
| 14 | Ignore-this: 1942dbd5378c70da60f79bb3b49fcb37 |
|---|
| 15 | ] { |
|---|
| 16 | adddir ./GHC/Integer/Logarithms |
|---|
| 17 | addfile ./GHC/Integer/Logarithms.hs |
|---|
| 18 | hunk ./GHC/Integer/Logarithms.hs 1 |
|---|
| 19 | +{-# LANGUAGE MagicHash, UnboxedTuples, NoImplicitPrelude #-} |
|---|
| 20 | +module GHC.Integer.Logarithms |
|---|
| 21 | + ( integerLogBase# |
|---|
| 22 | + , integerLog2# |
|---|
| 23 | + , wordLog2# |
|---|
| 24 | + ) where |
|---|
| 25 | + |
|---|
| 26 | +import GHC.Prim |
|---|
| 27 | +import GHC.Integer |
|---|
| 28 | +import qualified GHC.Integer.Logarithms.Internals as I |
|---|
| 29 | + |
|---|
| 30 | +-- | Calculate the integer logarithm for an arbitrary base. |
|---|
| 31 | +-- The base must be greater than 1, the second argument, the number |
|---|
| 32 | +-- whose logarithm is sought, should be positive, otherwise the |
|---|
| 33 | +-- result is meaningless. |
|---|
| 34 | +-- |
|---|
| 35 | +-- > |
|---|
| 36 | +-- base ^ integerLogBase# base m <= m < base ^ (integerLogBase# base m + 1) |
|---|
| 37 | +-- > |
|---|
| 38 | +-- |
|---|
| 39 | +-- for @base > 1@ and @m > 0@. |
|---|
| 40 | +integerLogBase# :: Integer -> Integer -> Int# |
|---|
| 41 | +integerLogBase# b m = case step b of |
|---|
| 42 | + (# _, e #) -> e |
|---|
| 43 | + where |
|---|
| 44 | + step pw = |
|---|
| 45 | + if m `ltInteger` pw |
|---|
| 46 | + then (# m, 0# #) |
|---|
| 47 | + else case step (pw `timesInteger` pw) of |
|---|
| 48 | + (# q, e #) -> |
|---|
| 49 | + if q `ltInteger` pw |
|---|
| 50 | + then (# q, 2# *# e #) |
|---|
| 51 | + else (# q `quotInteger` pw, 2# *# e +# 1# #) |
|---|
| 52 | + |
|---|
| 53 | +-- | Calculate the integer base 2 logarithm of an 'Integer'. |
|---|
| 54 | +-- The calculation is more efficient than for the general case, |
|---|
| 55 | +-- on platforms with 32- or 64-bit words much more efficient. |
|---|
| 56 | +-- |
|---|
| 57 | +-- The argument must be strictly positive, that condition is /not/ checked. |
|---|
| 58 | +integerLog2# :: Integer -> Int# |
|---|
| 59 | +integerLog2# = I.integerLog2# |
|---|
| 60 | + |
|---|
| 61 | +-- | This function calculates the integer base 2 logarithm of a 'Word#'. |
|---|
| 62 | +wordLog2# :: Word# -> Int# |
|---|
| 63 | +wordLog2# = I.wordLog2# |
|---|
| 64 | addfile ./GHC/Integer/Logarithms/Internals.hs |
|---|
| 65 | hunk ./GHC/Integer/Logarithms/Internals.hs 1 |
|---|
| 66 | +{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-} |
|---|
| 67 | +{-# OPTIONS_HADDOCK hide #-} |
|---|
| 68 | + |
|---|
| 69 | +#include "MachDeps.h" |
|---|
| 70 | + |
|---|
| 71 | +-- Fast integer logarithms to base 2. |
|---|
| 72 | +-- integerLog2# and wordLog2# are of general usefulness, |
|---|
| 73 | +-- the others are only needed for a fast implementation of |
|---|
| 74 | +-- fromRational. |
|---|
| 75 | +-- Since they are needed in GHC.Float, we must expose this |
|---|
| 76 | +-- module, but it should not show up in the docs. |
|---|
| 77 | + |
|---|
| 78 | +module GHC.Integer.Logarithms.Internals |
|---|
| 79 | + ( integerLog2# |
|---|
| 80 | + , integerLog2IsPowerOf2# |
|---|
| 81 | + , wordLog2# |
|---|
| 82 | + , roundingMode# |
|---|
| 83 | + ) where |
|---|
| 84 | + |
|---|
| 85 | +import GHC.Prim |
|---|
| 86 | +import GHC.Integer.Type |
|---|
| 87 | + |
|---|
| 88 | +-- When larger word sizes become common, add support for those, |
|---|
| 89 | +-- it is not hard, just tedious. |
|---|
| 90 | +#if (WORD_SIZE_IN_BITS != 32) && (WORD_SIZE_IN_BITS != 64) |
|---|
| 91 | + |
|---|
| 92 | +-- Less than ideal implementations for strange word sizes |
|---|
| 93 | + |
|---|
| 94 | +import GHC.Integer |
|---|
| 95 | + |
|---|
| 96 | +default () |
|---|
| 97 | + |
|---|
| 98 | +-- We do not know whether the word has 30 bits or 128 or even more, |
|---|
| 99 | +-- so we cannot start from the top, although that would be much more |
|---|
| 100 | +-- efficient. |
|---|
| 101 | +-- Count the bits until the highest set bit is found. |
|---|
| 102 | +wordLog2# :: Word# -> Int# |
|---|
| 103 | +wordLog2# w = go 8# w |
|---|
| 104 | + where |
|---|
| 105 | + go acc u = case u `uncheckedShiftRL#` 8# of |
|---|
| 106 | + 0## -> case leadingZeros of |
|---|
| 107 | + BA ba -> acc -# indexInt8Array# ba (word2Int# u) |
|---|
| 108 | + v -> go (acc +# 8#) v |
|---|
| 109 | + |
|---|
| 110 | +-- Assumption: Integer is strictly positive |
|---|
| 111 | +integerLog2# :: Integer -> Int# |
|---|
| 112 | +integerLog2# (S# i) = wordLog2# (int2Word# i) -- that is easy |
|---|
| 113 | +integerLog2# m = case step m (smallInteger 2#) 1# of |
|---|
| 114 | + (# _, l #) -> l |
|---|
| 115 | + where |
|---|
| 116 | + -- Invariants: |
|---|
| 117 | + -- pw = 2 ^ lg |
|---|
| 118 | + -- case step n pw lg of |
|---|
| 119 | + -- (q, e) -> pw^(2*e) <= n < pw^(2*e+2) |
|---|
| 120 | + -- && q <= n/pw^(2*e) < (q+1) |
|---|
| 121 | + -- && q < pw^2 |
|---|
| 122 | + step n pw lg = |
|---|
| 123 | + if n `ltInteger` pw |
|---|
| 124 | + then (# n, 0# #) |
|---|
| 125 | + else case step n (shiftLInteger pw lg) (2# *# lg) of |
|---|
| 126 | + (# q, e #) -> |
|---|
| 127 | + if q `ltInteger` pw |
|---|
| 128 | + then (# q, 2# *# e #) |
|---|
| 129 | + else (# q `shiftRInteger` lg, 2# *# e +# 1# #) |
|---|
| 130 | + |
|---|
| 131 | +-- Calculate the log2 of a positive integer and check |
|---|
| 132 | +-- whether it is a power of 2. |
|---|
| 133 | +-- By coincidence, the presence of a power of 2 is |
|---|
| 134 | +-- signalled by zero and not one. |
|---|
| 135 | +integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #) |
|---|
| 136 | +integerLog2IsPowerOf2# m = |
|---|
| 137 | + case integerLog2# m of |
|---|
| 138 | + lg -> if m `eqInteger` (smallInteger 1# `shiftLInteger` lg) |
|---|
| 139 | + then (# lg, 0# #) |
|---|
| 140 | + else (# lg, 1# #) |
|---|
| 141 | + |
|---|
| 142 | +-- Detect the rounding mode, |
|---|
| 143 | +-- 0# means round to zero, |
|---|
| 144 | +-- 1# means round to even, |
|---|
| 145 | +-- 2# means round away from zero |
|---|
| 146 | +roundingMode# :: Integer -> Int# -> Int# |
|---|
| 147 | +roundingMode# m h = |
|---|
| 148 | + case smallInteger 1# `shiftLInteger` h of |
|---|
| 149 | + c -> case m `andInteger` |
|---|
| 150 | + ((c `plusInteger` c) `minusInteger` smallInteger 1#) of |
|---|
| 151 | + r -> |
|---|
| 152 | + if c `ltInteger` r |
|---|
| 153 | + then 2# |
|---|
| 154 | + else if c `gtInteger` r |
|---|
| 155 | + then 0# |
|---|
| 156 | + else 1# |
|---|
| 157 | + |
|---|
| 158 | +#else |
|---|
| 159 | + |
|---|
| 160 | +default () |
|---|
| 161 | + |
|---|
| 162 | +-- We have a nice word size, we can do much better now. |
|---|
| 163 | + |
|---|
| 164 | +#if WORD_SIZE_IN_BITS == 32 |
|---|
| 165 | + |
|---|
| 166 | +#define WSHIFT 5 |
|---|
| 167 | +#define MMASK 31 |
|---|
| 168 | + |
|---|
| 169 | +#else |
|---|
| 170 | + |
|---|
| 171 | +#define WSHIFT 6 |
|---|
| 172 | +#define MMASK 63 |
|---|
| 173 | + |
|---|
| 174 | +#endif |
|---|
| 175 | + |
|---|
| 176 | +-- Assumption: Integer is strictly positive |
|---|
| 177 | +-- For small integers, use wordLog#, |
|---|
| 178 | +-- in the general case, check words from the most |
|---|
| 179 | +-- significant down, once a nonzero word is found, |
|---|
| 180 | +-- calculate its log2 and add the number of following bits. |
|---|
| 181 | +integerLog2# :: Integer -> Int# |
|---|
| 182 | +integerLog2# (S# i) = wordLog2# (int2Word# i) |
|---|
| 183 | +integerLog2# (J# s ba) = check (s -# 1#) |
|---|
| 184 | + where |
|---|
| 185 | + check i = case indexWordArray# ba i of |
|---|
| 186 | + 0## -> check (i -# 1#) |
|---|
| 187 | + w -> wordLog2# w +# (uncheckedIShiftL# i WSHIFT#) |
|---|
| 188 | + |
|---|
| 189 | +-- Assumption: Integer is strictly positive |
|---|
| 190 | +-- First component is log2 n, second is 0# iff n is a power of two |
|---|
| 191 | +integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #) |
|---|
| 192 | +-- The power of 2 test is n&(n-1) == 0, thus powers of 2 |
|---|
| 193 | +-- are indicated bythe second component being zero. |
|---|
| 194 | +integerLog2IsPowerOf2# (S# i) = |
|---|
| 195 | + case int2Word# i of |
|---|
| 196 | + w -> (# wordLog2# w, word2Int# (w `and#` (w `minusWord#` 1##)) #) |
|---|
| 197 | +-- Find the log2 as above, test whether that word is a power |
|---|
| 198 | +-- of 2, if so, check whether only zero bits follow. |
|---|
| 199 | +integerLog2IsPowerOf2# (J# s ba) = check (s -# 1#) |
|---|
| 200 | + where |
|---|
| 201 | + check :: Int# -> (# Int#, Int# #) |
|---|
| 202 | + check i = case indexWordArray# ba i of |
|---|
| 203 | + 0## -> check (i -# 1#) |
|---|
| 204 | + w -> (# wordLog2# w +# (uncheckedIShiftL# i WSHIFT#) |
|---|
| 205 | + , case w `and#` (w `minusWord#` 1##) of |
|---|
| 206 | + 0## -> test (i -# 1#) |
|---|
| 207 | + _ -> 1# #) |
|---|
| 208 | + test :: Int# -> Int# |
|---|
| 209 | + test i = if i <# 0# |
|---|
| 210 | + then 0# |
|---|
| 211 | + else case indexWordArray# ba i of |
|---|
| 212 | + 0## -> test (i -# 1#) |
|---|
| 213 | + _ -> 1# |
|---|
| 214 | + |
|---|
| 215 | +-- Assumption: Integer and Int# are strictly positive, Int# is less |
|---|
| 216 | +-- than logBase 2 of Integer, otherwise havoc ensues. |
|---|
| 217 | +-- Used only for the numerator in fromRational when the denominator |
|---|
| 218 | +-- is a power of 2. |
|---|
| 219 | +-- The Int# argument is log2 n minus the number of bits in the mantissa |
|---|
| 220 | +-- of the target type, i.e. the index of the first non-integral bit in |
|---|
| 221 | +-- the quotient. |
|---|
| 222 | +-- |
|---|
| 223 | +-- 0# means round down (towards zero) |
|---|
| 224 | +-- 1# means we have a half-integer, round to even |
|---|
| 225 | +-- 2# means round up (away from zero) |
|---|
| 226 | +roundingMode# :: Integer -> Int# -> Int# |
|---|
| 227 | +roundingMode# (S# i) t = |
|---|
| 228 | + case int2Word# i `and#` ((uncheckedShiftL# 2## t) `minusWord#` 1##) of |
|---|
| 229 | + k -> case uncheckedShiftL# 1## t of |
|---|
| 230 | + c -> if c `gtWord#` k |
|---|
| 231 | + then 0# |
|---|
| 232 | + else if c `ltWord#` k |
|---|
| 233 | + then 2# |
|---|
| 234 | + else 1# |
|---|
| 235 | +roundingMode# (J# _ ba) t = |
|---|
| 236 | + case word2Int# (int2Word# t `and#` MMASK##) of |
|---|
| 237 | + j -> -- index of relevant bit in word |
|---|
| 238 | + case uncheckedIShiftRA# t WSHIFT# of |
|---|
| 239 | + k -> -- index of relevant word |
|---|
| 240 | + case indexWordArray# ba k `and#` |
|---|
| 241 | + ((uncheckedShiftL# 2## j) `minusWord#` 1##) of |
|---|
| 242 | + r -> |
|---|
| 243 | + case uncheckedShiftL# 1## j of |
|---|
| 244 | + c -> if c `gtWord#` r |
|---|
| 245 | + then 0# |
|---|
| 246 | + else if c `ltWord#` r |
|---|
| 247 | + then 2# |
|---|
| 248 | + else test (k -# 1#) |
|---|
| 249 | + where |
|---|
| 250 | + test i = if i <# 0# |
|---|
| 251 | + then 1# |
|---|
| 252 | + else case indexWordArray# ba i of |
|---|
| 253 | + 0## -> test (i -# 1#) |
|---|
| 254 | + _ -> 2# |
|---|
| 255 | + |
|---|
| 256 | +-- wordLog2# 0## = -1# |
|---|
| 257 | +{-# INLINE wordLog2# #-} |
|---|
| 258 | +wordLog2# :: Word# -> Int# |
|---|
| 259 | +wordLog2# w = |
|---|
| 260 | + case leadingZeros of |
|---|
| 261 | + BA lz -> |
|---|
| 262 | + let zeros u = indexInt8Array# lz (word2Int# u) in |
|---|
| 263 | +#if WORD_SIZE_IN_BITS == 64 |
|---|
| 264 | + case uncheckedShiftRL# w 56# of |
|---|
| 265 | + a -> |
|---|
| 266 | + if a `neWord#` 0## |
|---|
| 267 | + then 64# -# zeros a |
|---|
| 268 | + else |
|---|
| 269 | + case uncheckedShiftRL# w 48# of |
|---|
| 270 | + b -> |
|---|
| 271 | + if b `neWord#` 0## |
|---|
| 272 | + then 56# -# zeros b |
|---|
| 273 | + else |
|---|
| 274 | + case uncheckedShiftRL# w 40# of |
|---|
| 275 | + c -> |
|---|
| 276 | + if c `neWord#` 0## |
|---|
| 277 | + then 48# -# zeros c |
|---|
| 278 | + else |
|---|
| 279 | + case uncheckedShiftRL# w 32# of |
|---|
| 280 | + d -> |
|---|
| 281 | + if d `neWord#` 0## |
|---|
| 282 | + then 40# -# zeros d |
|---|
| 283 | + else |
|---|
| 284 | +#endif |
|---|
| 285 | + case uncheckedShiftRL# w 24# of |
|---|
| 286 | + e -> |
|---|
| 287 | + if e `neWord#` 0## |
|---|
| 288 | + then 32# -# zeros e |
|---|
| 289 | + else |
|---|
| 290 | + case uncheckedShiftRL# w 16# of |
|---|
| 291 | + f -> |
|---|
| 292 | + if f `neWord#` 0## |
|---|
| 293 | + then 24# -# zeros f |
|---|
| 294 | + else |
|---|
| 295 | + case uncheckedShiftRL# w 8# of |
|---|
| 296 | + g -> |
|---|
| 297 | + if g `neWord#` 0## |
|---|
| 298 | + then 16# -# zeros g |
|---|
| 299 | + else 8# -# zeros w |
|---|
| 300 | + |
|---|
| 301 | +#endif |
|---|
| 302 | + |
|---|
| 303 | +-- Lookup table |
|---|
| 304 | +data BA = BA ByteArray# |
|---|
| 305 | + |
|---|
| 306 | +leadingZeros :: BA |
|---|
| 307 | +leadingZeros = |
|---|
| 308 | + let mkArr s = |
|---|
| 309 | + case newByteArray# 256# s of |
|---|
| 310 | + (# s1, mba #) -> |
|---|
| 311 | + case writeInt8Array# mba 0# 9# s1 of |
|---|
| 312 | + s2 -> |
|---|
| 313 | + let fillA lim val idx st = |
|---|
| 314 | + if idx ==# 256# |
|---|
| 315 | + then st |
|---|
| 316 | + else if idx <# lim |
|---|
| 317 | + then case writeInt8Array# mba idx val st of |
|---|
| 318 | + nx -> fillA lim val (idx +# 1#) nx |
|---|
| 319 | + else fillA (2# *# lim) (val -# 1#) idx st |
|---|
| 320 | + in case fillA 2# 8# 1# s2 of |
|---|
| 321 | + s3 -> case unsafeFreezeByteArray# mba s3 of |
|---|
| 322 | + (# _, ba #) -> ba |
|---|
| 323 | + in case mkArr realWorld# of |
|---|
| 324 | + b -> BA b |
|---|
| 325 | hunk ./integer-gmp.cabal 26 |
|---|
| 326 | build-depends: ghc-prim |
|---|
| 327 | exposed-modules: GHC.Integer |
|---|
| 328 | GHC.Integer.GMP.Internals |
|---|
| 329 | + GHC.Integer.Logarithms |
|---|
| 330 | + GHC.Integer.Logarithms.Internals |
|---|
| 331 | other-modules: GHC.Integer.Type |
|---|
| 332 | extensions: CPP, MagicHash, UnboxedTuples, NoImplicitPrelude, |
|---|
| 333 | ForeignFunctionInterface, UnliftedFFITypes |
|---|
| 334 | } |
|---|
| 335 | [Fix Haddock markup |
|---|
| 336 | Daniel Fischer <daniel.is.fischer@googlemail.com>**20110330231710 |
|---|
| 337 | Ignore-this: ad1657f7c2e512a41f9d53a77d799013 |
|---|
| 338 | ] hunk ./GHC/Integer/Logarithms.hs 17 |
|---|
| 339 | -- whose logarithm is sought, should be positive, otherwise the |
|---|
| 340 | -- result is meaningless. |
|---|
| 341 | -- |
|---|
| 342 | --- > |
|---|
| 343 | --- base ^ integerLogBase# base m <= m < base ^ (integerLogBase# base m + 1) |
|---|
| 344 | --- > |
|---|
| 345 | +-- > base ^ integerLogBase# base m <= m < base ^ (integerLogBase# base m + 1) |
|---|
| 346 | -- |
|---|
| 347 | -- for @base > 1@ and @m > 0@. |
|---|
| 348 | integerLogBase# :: Integer -> Integer -> Int# |
|---|
| 349 | |
|---|
| 350 | Context: |
|---|
| 351 | |
|---|
| 352 | [Call the final build system phase "final" rather than "" |
|---|
| 353 | Ian Lynagh <igloo@earth.li>**20110206203232 |
|---|
| 354 | Ignore-this: 929994164005f2449ee56ab8a0c07fab |
|---|
| 355 | ] |
|---|
| 356 | [Update for changes in GHC's build system |
|---|
| 357 | Ian Lynagh <igloo@earth.li>**20110122194756 |
|---|
| 358 | Ignore-this: e4e98a7ff8a7800f228f59e9452746cf |
|---|
| 359 | ] |
|---|
| 360 | [Correct the gmp build phase |
|---|
| 361 | Ian Lynagh <igloo@earth.li>**20110117122245 |
|---|
| 362 | Ignore-this: bc26aafe9526a942f5a381fb3688d7a9 |
|---|
| 363 | ] |
|---|
| 364 | [Tidy up gmp cleaning |
|---|
| 365 | Ian Lynagh <igloo@earth.li>**20110117121224 |
|---|
| 366 | Ignore-this: 25007c0d1482705f5390e29a86ed6a66 |
|---|
| 367 | ] |
|---|
| 368 | [Add extensions to LANGUAGE pragmas |
|---|
| 369 | Ian Lynagh <igloo@earth.li>**20110111003050] |
|---|
| 370 | [Fix unknown symbol base_ControlziExceptionziBase_patError_info by helping GHC generate smarter core. |
|---|
| 371 | Edward Z. Yang <ezyang@mit.edu>**20101204013010 |
|---|
| 372 | Ignore-this: df2991ab1f4321c8777af7f7c1415d29 |
|---|
| 373 | ] |
|---|
| 374 | [Add LANGUAGE BangPatterns to modules that use bang patterns |
|---|
| 375 | simonpj@microsoft.com**20101112170604 |
|---|
| 376 | Ignore-this: bd8280707c084644c185d5fb01e583f0 |
|---|
| 377 | ] |
|---|
| 378 | [Add a rewrite rule for toInt# so literals work right |
|---|
| 379 | simonpj@microsoft.com**20101026082955 |
|---|
| 380 | Ignore-this: 2e7646769926eebff6e49d84e1271089 |
|---|
| 381 | |
|---|
| 382 | See the comments with toInt#, but the key point is |
|---|
| 383 | that we want (fromInteger 1)::Int to yield (I# 1)! |
|---|
| 384 | ] |
|---|
| 385 | [Follow GHC.Bool/GHC.Types merge |
|---|
| 386 | Ian Lynagh <igloo@earth.li>**20101023153631 |
|---|
| 387 | Ignore-this: 4ce6102919eccb7335756bd4001a2322 |
|---|
| 388 | ] |
|---|
| 389 | [Bump version number to 0.2.0.2 |
|---|
| 390 | Ian Lynagh <igloo@earth.li>**20100916170032] |
|---|
| 391 | [Fix compile warning on 32bit machine |
|---|
| 392 | David Terei <davidterei@gmail.com>**20100817103407 |
|---|
| 393 | Ignore-this: 30b715c759d3721a4651c3c94054813 |
|---|
| 394 | ] |
|---|
| 395 | [fix hashInteger to be the same as fromIntegral, and document it (#4108) |
|---|
| 396 | Simon Marlow <marlowsd@gmail.com>**20100813153142 |
|---|
| 397 | Ignore-this: 5778949a68115bd65464b2b3d4bf4834 |
|---|
| 398 | ] |
|---|
| 399 | [implement integer2Int# and integer2Word# in Haskell, not foreign prim |
|---|
| 400 | Simon Marlow <marlowsd@gmail.com>**20100813152926 |
|---|
| 401 | Ignore-this: e06beace47751538e72e7b1615ff6dcf |
|---|
| 402 | ] |
|---|
| 403 | [Use the stage-specific CONF_CC_OPTS variables |
|---|
| 404 | Ian Lynagh <igloo@earth.li>**20100723135933] |
|---|
| 405 | [TAG Haskell 2010 report generated |
|---|
| 406 | Simon Marlow <marlowsd@gmail.com>**20100705150919 |
|---|
| 407 | Ignore-this: 9e76b0809ef3e0cd86b2dd0efb9c0fb7 |
|---|
| 408 | ] |
|---|
| 409 | Patch bundle hash: |
|---|
| 410 | e5680d9c3fb3479e4478757e0dbb7c7d4393d2eb |
|---|