| 1 | 1 patch for repository /home/dafis/Haskell/Hacking/ghc/libraries/integer-gmp: |
|---|
| 2 | |
|---|
| 3 | Mon Oct 25 21:52:50 CEST 2010 Daniel Fischer <daniel.is.fischer@web.de> |
|---|
| 4 | * Logarithms for integer-gmp |
|---|
| 5 | Fast integer logarithms as needed for fromRational. |
|---|
| 6 | |
|---|
| 7 | New patches: |
|---|
| 8 | |
|---|
| 9 | [Logarithms for integer-gmp |
|---|
| 10 | Daniel Fischer <daniel.is.fischer@web.de>**20101025195250 |
|---|
| 11 | Ignore-this: 22e961bde127107d40fcc91f77ba9483 |
|---|
| 12 | Fast integer logarithms as needed for fromRational. |
|---|
| 13 | ] { |
|---|
| 14 | adddir ./GHC/Integer/Logarithms |
|---|
| 15 | addfile ./GHC/Integer/Logarithms.hs |
|---|
| 16 | hunk ./GHC/Integer/Logarithms.hs 1 |
|---|
| 17 | +{-# LANGUAGE MagicHash, UnboxedTuples, NoImplicitPrelude #-} |
|---|
| 18 | +module GHC.Integer.Logarithms |
|---|
| 19 | + ( integerLogBase# |
|---|
| 20 | + , integerLog2# |
|---|
| 21 | + , wordLog2# |
|---|
| 22 | + ) where |
|---|
| 23 | + |
|---|
| 24 | +import GHC.Prim |
|---|
| 25 | +import GHC.Integer |
|---|
| 26 | +import qualified GHC.Integer.Logarithms.Internals as I |
|---|
| 27 | + |
|---|
| 28 | +-- | Calculate the integer logarithm for an arbitrary base. |
|---|
| 29 | +-- The base must be greater than 1, the second argument, the number |
|---|
| 30 | +-- whose logarithm is sought, should be positive, otherwise the |
|---|
| 31 | +-- result is meaningless. |
|---|
| 32 | +-- |
|---|
| 33 | +-- > |
|---|
| 34 | +-- base ^ integerLogBase# base m <= m < base ^ (integerLogBase# base m + 1) |
|---|
| 35 | +-- > |
|---|
| 36 | +-- |
|---|
| 37 | +-- for @base > 1@ and @m > 0@. |
|---|
| 38 | +integerLogBase# :: Integer -> Integer -> Int# |
|---|
| 39 | +integerLogBase# b m = case step b of |
|---|
| 40 | + (# _, e #) -> e |
|---|
| 41 | + where |
|---|
| 42 | + step pw = |
|---|
| 43 | + if m `ltInteger` pw |
|---|
| 44 | + then (# m, 0# #) |
|---|
| 45 | + else case step (pw `timesInteger` pw) of |
|---|
| 46 | + (# q, e #) -> |
|---|
| 47 | + if q `ltInteger` pw |
|---|
| 48 | + then (# q, 2# *# e #) |
|---|
| 49 | + else (# q `quotInteger` pw, 2# *# e +# 1# #) |
|---|
| 50 | + |
|---|
| 51 | +-- | Calculate the integer base 2 logarithm of an 'Integer'. |
|---|
| 52 | +-- The calculation is more efficient than for the general case, |
|---|
| 53 | +-- on platforms with 32- or 64-bit words much more efficient. |
|---|
| 54 | +-- |
|---|
| 55 | +-- The argument must be strictly positive, that condition is /not/ checked. |
|---|
| 56 | +integerLog2# :: Integer -> Int# |
|---|
| 57 | +integerLog2# = I.integerLog2# |
|---|
| 58 | + |
|---|
| 59 | +-- | This function calculates the integer base 2 logarithm of a 'Word#'. |
|---|
| 60 | +wordLog2# :: Word# -> Int# |
|---|
| 61 | +wordLog2# = I.wordLog2# |
|---|
| 62 | addfile ./GHC/Integer/Logarithms/Internals.hs |
|---|
| 63 | hunk ./GHC/Integer/Logarithms/Internals.hs 1 |
|---|
| 64 | +{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-} |
|---|
| 65 | +{-# OPTIONS_HADDOCK hide #-} |
|---|
| 66 | + |
|---|
| 67 | +#include "MachDeps.h" |
|---|
| 68 | + |
|---|
| 69 | +module GHC.Integer.Logarithms.Internals |
|---|
| 70 | + ( integerLog2# |
|---|
| 71 | + , integerLog2IsPowerOf2# |
|---|
| 72 | + , wordLog2# |
|---|
| 73 | + , roundingMode# |
|---|
| 74 | + ) where |
|---|
| 75 | + |
|---|
| 76 | +import GHC.Prim |
|---|
| 77 | +import GHC.Integer.Type |
|---|
| 78 | + |
|---|
| 79 | +-- When larger word sizes become common, add support for those, |
|---|
| 80 | +-- it is not hard, just tedious. |
|---|
| 81 | +#if (WORD_SIZE_IN_BITS != 32) && (WORD_SIZE_IN_BITS != 64) |
|---|
| 82 | + |
|---|
| 83 | +import GHC.Integer |
|---|
| 84 | + |
|---|
| 85 | +default () |
|---|
| 86 | + |
|---|
| 87 | +-- We do not know whether the word has 30 bits or 128 or even more, |
|---|
| 88 | +-- so we cannot start from the top, although that would be much more |
|---|
| 89 | +-- efficient. |
|---|
| 90 | +wordLog2# :: Word# -> Int# |
|---|
| 91 | +wordLog2# w = go 8# w |
|---|
| 92 | + where |
|---|
| 93 | + go acc u = case u `uncheckedShiftRL#` 8# of |
|---|
| 94 | + 0## -> case leadingZeros of |
|---|
| 95 | + BA ba -> acc -# indexInt8Array# ba (word2Int# u) |
|---|
| 96 | + v -> go (acc +# 8#) v |
|---|
| 97 | + |
|---|
| 98 | +-- Assumption: Integer is strictly positive |
|---|
| 99 | +integerLog2# :: Integer -> Int# |
|---|
| 100 | +integerLog2# (S# i) = wordLog2# (int2Word# i) -- that one is easy |
|---|
| 101 | +integerLog2# m = case step m (smallInteger 2#) 1# of |
|---|
| 102 | + (# _, l #) -> l |
|---|
| 103 | + where |
|---|
| 104 | + -- Invariants: |
|---|
| 105 | + -- pw = 2 ^ lg |
|---|
| 106 | + -- case step n pw lg of |
|---|
| 107 | + -- (q, e) -> pw^(2*e) <= n < pw^(2*e+2) |
|---|
| 108 | + -- && q <= n/pw^(2*e) < (q+1) |
|---|
| 109 | + -- && q < pw^2 |
|---|
| 110 | + step n pw lg = |
|---|
| 111 | + if n `ltInteger` pw |
|---|
| 112 | + then (# n, 0# #) |
|---|
| 113 | + else case step n (shiftLInteger pw lg) (2# *# lg) of |
|---|
| 114 | + (# q, e #) -> |
|---|
| 115 | + if q `ltInteger` pw |
|---|
| 116 | + then (# q, 2# *# e #) |
|---|
| 117 | + else (# q `shiftRInteger` lg, 2# *# e +# 1# #) |
|---|
| 118 | + |
|---|
| 119 | +integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #) |
|---|
| 120 | +integerLog2IsPowerOf2# m = |
|---|
| 121 | + case integerLog2# m of |
|---|
| 122 | + lg -> if m `eqInteger` (smallInteger 1# `shiftLInteger` lg) |
|---|
| 123 | + then (# lg, 0# #) |
|---|
| 124 | + else (# lg, 1# #) |
|---|
| 125 | + |
|---|
| 126 | +roundingMode# :: Integer -> Int# -> Int# |
|---|
| 127 | +roundingMode# m h = |
|---|
| 128 | + case smallInteger 1# `shiftLInteger` h of |
|---|
| 129 | + c -> case m `andInteger` |
|---|
| 130 | + ((c `plusInteger` c) `minusInteger` smallInteger 1#) of |
|---|
| 131 | + r -> |
|---|
| 132 | + if c `ltInteger` r |
|---|
| 133 | + then 2# |
|---|
| 134 | + else if c `gtInteger` r |
|---|
| 135 | + then 0# |
|---|
| 136 | + else 1# |
|---|
| 137 | + |
|---|
| 138 | +#else |
|---|
| 139 | + |
|---|
| 140 | +default () |
|---|
| 141 | + |
|---|
| 142 | +-- We have a nice word size, we can do much better now. |
|---|
| 143 | + |
|---|
| 144 | +#if WORD_SIZE_IN_BITS == 32 |
|---|
| 145 | + |
|---|
| 146 | +#define WSHIFT 5 |
|---|
| 147 | +#define MMASK 31 |
|---|
| 148 | + |
|---|
| 149 | +#else |
|---|
| 150 | + |
|---|
| 151 | +#define WSHIFT 6 |
|---|
| 152 | +#define MMASK 63 |
|---|
| 153 | + |
|---|
| 154 | +#endif |
|---|
| 155 | + |
|---|
| 156 | +-- Assumption: Integer is strictly positive |
|---|
| 157 | +integerLog2# :: Integer -> Int# |
|---|
| 158 | +integerLog2# (S# i) = wordLog2# (int2Word# i) |
|---|
| 159 | +integerLog2# (J# s ba) = check (s -# 1#) |
|---|
| 160 | + where |
|---|
| 161 | + check i = case indexWordArray# ba i of |
|---|
| 162 | + 0## -> check (i -# 1#) |
|---|
| 163 | + w -> wordLog2# w +# (uncheckedIShiftL# i WSHIFT#) |
|---|
| 164 | + |
|---|
| 165 | +-- Assumption: Integer is strictly positive |
|---|
| 166 | +-- First component is log2 n, second is 0# iff n is a power of two |
|---|
| 167 | +integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #) |
|---|
| 168 | +integerLog2IsPowerOf2# (S# i) = |
|---|
| 169 | + case int2Word# i of |
|---|
| 170 | + w -> (# wordLog2# w, word2Int# (w `and#` (w `minusWord#` 1##)) #) |
|---|
| 171 | +integerLog2IsPowerOf2# (J# s ba) = check (s -# 1#) |
|---|
| 172 | + where |
|---|
| 173 | + check :: Int# -> (# Int#, Int# #) |
|---|
| 174 | + check i = case indexWordArray# ba i of |
|---|
| 175 | + 0## -> check (i -# 1#) |
|---|
| 176 | + w -> (# wordLog2# w +# (uncheckedIShiftL# i WSHIFT#) |
|---|
| 177 | + , case w `and#` (w `minusWord#` 1##) of |
|---|
| 178 | + 0## -> test (i -# 1#) |
|---|
| 179 | + _ -> 1# #) |
|---|
| 180 | + test :: Int# -> Int# |
|---|
| 181 | + test i = if i <# 0# |
|---|
| 182 | + then 0# |
|---|
| 183 | + else case indexWordArray# ba i of |
|---|
| 184 | + 0## -> test (i -# 1#) |
|---|
| 185 | + _ -> 1# |
|---|
| 186 | + |
|---|
| 187 | +-- Assumption: Integer and Int# are strictly positive, Int# is less |
|---|
| 188 | +-- than logBase 2 of Integer, otherwise havoc ensues. |
|---|
| 189 | +-- Used only for the numerator in fromRational when the denominator |
|---|
| 190 | +-- is a power of 2. |
|---|
| 191 | +-- The Int# argument is log2 n minus the number of bits in the mantissa |
|---|
| 192 | +-- of the target type, i.e. the index of the first non-integral bit in |
|---|
| 193 | +-- the quotient. |
|---|
| 194 | +-- |
|---|
| 195 | +-- 0# means round down (towards zero) |
|---|
| 196 | +-- 1# means we have a half-integer, round to even |
|---|
| 197 | +-- 2# means round up (away from zero) |
|---|
| 198 | +roundingMode# :: Integer -> Int# -> Int# |
|---|
| 199 | +roundingMode# (S# i) t = |
|---|
| 200 | + case int2Word# i `and#` ((uncheckedShiftL# 2## t) `minusWord#` 1##) of |
|---|
| 201 | + k -> case uncheckedShiftL# 1## t of |
|---|
| 202 | + c -> if c `gtWord#` k |
|---|
| 203 | + then 0# |
|---|
| 204 | + else if c `ltWord#` k |
|---|
| 205 | + then 2# |
|---|
| 206 | + else 1# |
|---|
| 207 | +roundingMode# (J# _ ba) t = |
|---|
| 208 | + case word2Int# (int2Word# t `and#` MMASK##) of |
|---|
| 209 | + j -> |
|---|
| 210 | + case uncheckedIShiftRA# t WSHIFT# of |
|---|
| 211 | + k -> |
|---|
| 212 | + case indexWordArray# ba k `and#` |
|---|
| 213 | + ((uncheckedShiftL# 2## j) `minusWord#` 1##) of |
|---|
| 214 | + r -> |
|---|
| 215 | + case uncheckedShiftL# 1## j of |
|---|
| 216 | + c -> if c `gtWord#` r |
|---|
| 217 | + then 0# |
|---|
| 218 | + else if c `ltWord#` r |
|---|
| 219 | + then 2# |
|---|
| 220 | + else test (k -# 1#) |
|---|
| 221 | + where |
|---|
| 222 | + test i = if i <# 0# |
|---|
| 223 | + then 0# |
|---|
| 224 | + else case indexWordArray# ba i of |
|---|
| 225 | + 0## -> test (i -# 1#) |
|---|
| 226 | + _ -> 2# |
|---|
| 227 | + |
|---|
| 228 | +-- wordLog2# 0## = -1# |
|---|
| 229 | +{-# INLINE wordLog2# #-} |
|---|
| 230 | +wordLog2# :: Word# -> Int# |
|---|
| 231 | +wordLog2# w = |
|---|
| 232 | + case leadingZeros of |
|---|
| 233 | + BA lz -> |
|---|
| 234 | + let zeros u = indexInt8Array# lz (word2Int# u) in |
|---|
| 235 | +#if WORD_SIZE_IN_BITS == 64 |
|---|
| 236 | + case uncheckedShiftRL# w 56# of |
|---|
| 237 | + a -> |
|---|
| 238 | + if a `neWord#` 0## |
|---|
| 239 | + then 64# -# zeros a |
|---|
| 240 | + else |
|---|
| 241 | + case uncheckedShiftRL# w 48# of |
|---|
| 242 | + b -> |
|---|
| 243 | + if b `neWord#` 0## |
|---|
| 244 | + then 56# -# zeros b |
|---|
| 245 | + else |
|---|
| 246 | + case uncheckedShiftRL# w 40# of |
|---|
| 247 | + c -> |
|---|
| 248 | + if c `neWord#` 0## |
|---|
| 249 | + then 48# -# zeros c |
|---|
| 250 | + else |
|---|
| 251 | + case uncheckedShiftRL# w 32# of |
|---|
| 252 | + d -> |
|---|
| 253 | + if d `neWord#` 0## |
|---|
| 254 | + then 40# -# zeros d |
|---|
| 255 | + else |
|---|
| 256 | +#endif |
|---|
| 257 | + case uncheckedShiftRL# w 24# of |
|---|
| 258 | + e -> |
|---|
| 259 | + if e `neWord#` 0## |
|---|
| 260 | + then 32# -# zeros e |
|---|
| 261 | + else |
|---|
| 262 | + case uncheckedShiftRL# w 16# of |
|---|
| 263 | + f -> |
|---|
| 264 | + if f `neWord#` 0## |
|---|
| 265 | + then 24# -# zeros f |
|---|
| 266 | + else |
|---|
| 267 | + case uncheckedShiftRL# w 8# of |
|---|
| 268 | + g -> |
|---|
| 269 | + if g `neWord#` 0## |
|---|
| 270 | + then 16# -# zeros g |
|---|
| 271 | + else 8# -# zeros w |
|---|
| 272 | + |
|---|
| 273 | +#endif |
|---|
| 274 | + |
|---|
| 275 | +-- Lookup table |
|---|
| 276 | +data BA = BA ByteArray# |
|---|
| 277 | + |
|---|
| 278 | +leadingZeros :: BA |
|---|
| 279 | +leadingZeros = |
|---|
| 280 | + let mkArr s = |
|---|
| 281 | + case newByteArray# 256# s of |
|---|
| 282 | + (# s1, mba #) -> |
|---|
| 283 | + case writeInt8Array# mba 0# 9# s1 of |
|---|
| 284 | + s2 -> |
|---|
| 285 | + let fillA lim val idx st = |
|---|
| 286 | + if idx ==# 256# |
|---|
| 287 | + then st |
|---|
| 288 | + else if idx <# lim |
|---|
| 289 | + then case writeInt8Array# mba idx val st of |
|---|
| 290 | + nx -> fillA lim val (idx +# 1#) nx |
|---|
| 291 | + else fillA (2# *# lim) (val -# 1#) idx st |
|---|
| 292 | + in case fillA 2# 8# 1# s2 of |
|---|
| 293 | + s3 -> case unsafeFreezeByteArray# mba s3 of |
|---|
| 294 | + (# _, ba #) -> ba |
|---|
| 295 | + in case mkArr realWorld# of |
|---|
| 296 | + b -> BA b |
|---|
| 297 | hunk ./integer-gmp.cabal 26 |
|---|
| 298 | build-depends: ghc-prim |
|---|
| 299 | exposed-modules: GHC.Integer |
|---|
| 300 | GHC.Integer.GMP.Internals |
|---|
| 301 | + GHC.Integer.Logarithms |
|---|
| 302 | + GHC.Integer.Logarithms.Internals |
|---|
| 303 | other-modules: GHC.Integer.Type |
|---|
| 304 | extensions: CPP, MagicHash, UnboxedTuples, NoImplicitPrelude, |
|---|
| 305 | ForeignFunctionInterface, UnliftedFFITypes |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | Context: |
|---|
| 309 | |
|---|
| 310 | [Follow GHC.Bool/GHC.Types merge |
|---|
| 311 | Ian Lynagh <igloo@earth.li>**20101023153631 |
|---|
| 312 | Ignore-this: 4ce6102919eccb7335756bd4001a2322 |
|---|
| 313 | ] |
|---|
| 314 | [Bump version number to 0.2.0.2 |
|---|
| 315 | Ian Lynagh <igloo@earth.li>**20100916170032] |
|---|
| 316 | [Fix compile warning on 32bit machine |
|---|
| 317 | David Terei <davidterei@gmail.com>**20100817103407 |
|---|
| 318 | Ignore-this: 30b715c759d3721a4651c3c94054813 |
|---|
| 319 | ] |
|---|
| 320 | [fix hashInteger to be the same as fromIntegral, and document it (#4108) |
|---|
| 321 | Simon Marlow <marlowsd@gmail.com>**20100813153142 |
|---|
| 322 | Ignore-this: 5778949a68115bd65464b2b3d4bf4834 |
|---|
| 323 | ] |
|---|
| 324 | [implement integer2Int# and integer2Word# in Haskell, not foreign prim |
|---|
| 325 | Simon Marlow <marlowsd@gmail.com>**20100813152926 |
|---|
| 326 | Ignore-this: e06beace47751538e72e7b1615ff6dcf |
|---|
| 327 | ] |
|---|
| 328 | [Use the stage-specific CONF_CC_OPTS variables |
|---|
| 329 | Ian Lynagh <igloo@earth.li>**20100723135933] |
|---|
| 330 | [TAG Haskell 2010 report generated |
|---|
| 331 | Simon Marlow <marlowsd@gmail.com>**20100705150919 |
|---|
| 332 | Ignore-this: 9e76b0809ef3e0cd86b2dd0efb9c0fb7 |
|---|
| 333 | ] |
|---|
| 334 | Patch bundle hash: |
|---|
| 335 | 93328dc2e5b9a98fdd40cb108cc3a05a9cd63ba0 |
|---|