| 1 | 1 patch for repository /home/dafis/Haskell/Hacking/ghc/libraries/integer-simple: |
|---|
| 2 | |
|---|
| 3 | Mon Oct 25 21:56:27 CEST 2010 Daniel Fischer <daniel.is.fischer@web.de> |
|---|
| 4 | * Logarithms for integer-simple |
|---|
| 5 | Integer logarithms as needed for fromRational. |
|---|
| 6 | So far, they have not been optimised at all. |
|---|
| 7 | |
|---|
| 8 | New patches: |
|---|
| 9 | |
|---|
| 10 | [Logarithms for integer-simple |
|---|
| 11 | Daniel Fischer <daniel.is.fischer@web.de>**20101025195627 |
|---|
| 12 | Ignore-this: f720182ed430fcc6788e3296ea250e3c |
|---|
| 13 | Integer logarithms as needed for fromRational. |
|---|
| 14 | So far, they have not been optimised at all. |
|---|
| 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 should be more efficient than for the general case. |
|---|
| 55 | +-- |
|---|
| 56 | +-- The argument must be strictly positive, that condition is /not/ checked. |
|---|
| 57 | +integerLog2# :: Integer -> Int# |
|---|
| 58 | +integerLog2# = I.integerLog2# |
|---|
| 59 | + |
|---|
| 60 | +-- | This function calculates the integer base 2 logarithm of a 'Word#'. |
|---|
| 61 | +wordLog2# :: Word# -> Int# |
|---|
| 62 | +wordLog2# = I.wordLog2# |
|---|
| 63 | addfile ./GHC/Integer/Logarithms/Internals.hs |
|---|
| 64 | hunk ./GHC/Integer/Logarithms/Internals.hs 1 |
|---|
| 65 | +{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-} |
|---|
| 66 | +{-# OPTIONS_HADDOCK hide #-} |
|---|
| 67 | + |
|---|
| 68 | +#include "MachDeps.h" |
|---|
| 69 | + |
|---|
| 70 | +module GHC.Integer.Logarithms.Internals |
|---|
| 71 | + ( integerLog2# |
|---|
| 72 | + , integerLog2IsPowerOf2# |
|---|
| 73 | + , wordLog2# |
|---|
| 74 | + , roundingMode# |
|---|
| 75 | + ) where |
|---|
| 76 | + |
|---|
| 77 | +import GHC.Prim |
|---|
| 78 | +import GHC.Integer.Type |
|---|
| 79 | +import GHC.Integer |
|---|
| 80 | + |
|---|
| 81 | +default () |
|---|
| 82 | + |
|---|
| 83 | +-- When larger word sizes become common, add support for those, |
|---|
| 84 | +-- it is not hard, just tedious. |
|---|
| 85 | +#if (WORD_SIZE_IN_BITS != 32) && (WORD_SIZE_IN_BITS != 64) |
|---|
| 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 | +#else |
|---|
| 99 | + |
|---|
| 100 | +-- This one at least can also be done efficiently. |
|---|
| 101 | +-- wordLog2# 0## = -1# |
|---|
| 102 | +{-# INLINE wordLog2# #-} |
|---|
| 103 | +wordLog2# :: Word# -> Int# |
|---|
| 104 | +wordLog2# w = |
|---|
| 105 | + case leadingZeros of |
|---|
| 106 | + BA lz -> |
|---|
| 107 | + let zeros u = indexInt8Array# lz (word2Int# u) in |
|---|
| 108 | +#if WORD_SIZE_IN_BITS == 64 |
|---|
| 109 | + case uncheckedShiftRL# w 56# of |
|---|
| 110 | + a -> |
|---|
| 111 | + if a `neWord#` 0## |
|---|
| 112 | + then 64# -# zeros a |
|---|
| 113 | + else |
|---|
| 114 | + case uncheckedShiftRL# w 48# of |
|---|
| 115 | + b -> |
|---|
| 116 | + if b `neWord#` 0## |
|---|
| 117 | + then 56# -# zeros b |
|---|
| 118 | + else |
|---|
| 119 | + case uncheckedShiftRL# w 40# of |
|---|
| 120 | + c -> |
|---|
| 121 | + if c `neWord#` 0## |
|---|
| 122 | + then 48# -# zeros c |
|---|
| 123 | + else |
|---|
| 124 | + case uncheckedShiftRL# w 32# of |
|---|
| 125 | + d -> |
|---|
| 126 | + if d `neWord#` 0## |
|---|
| 127 | + then 40# -# zeros d |
|---|
| 128 | + else |
|---|
| 129 | +#endif |
|---|
| 130 | + case uncheckedShiftRL# w 24# of |
|---|
| 131 | + e -> |
|---|
| 132 | + if e `neWord#` 0## |
|---|
| 133 | + then 32# -# zeros e |
|---|
| 134 | + else |
|---|
| 135 | + case uncheckedShiftRL# w 16# of |
|---|
| 136 | + f -> |
|---|
| 137 | + if f `neWord#` 0## |
|---|
| 138 | + then 24# -# zeros f |
|---|
| 139 | + else |
|---|
| 140 | + case uncheckedShiftRL# w 8# of |
|---|
| 141 | + g -> |
|---|
| 142 | + if g `neWord#` 0## |
|---|
| 143 | + then 16# -# zeros g |
|---|
| 144 | + else 8# -# zeros w |
|---|
| 145 | + |
|---|
| 146 | +#endif |
|---|
| 147 | + |
|---|
| 148 | +-- As for the rest, I will see later what efficiency we can gain. |
|---|
| 149 | + |
|---|
| 150 | +-- Assumption: Integer is strictly positive |
|---|
| 151 | +integerLog2# :: Integer -> Int# |
|---|
| 152 | +integerLog2# m = case step m (smallInteger 2#) 1# of |
|---|
| 153 | + (# _, l #) -> l |
|---|
| 154 | + where |
|---|
| 155 | + -- Invariants: |
|---|
| 156 | + -- pw = 2 ^ lg |
|---|
| 157 | + -- case step n pw lg of |
|---|
| 158 | + -- (q, e) -> pw^(2*e) <= n < pw^(2*e+2) |
|---|
| 159 | + -- && q <= n/pw^(2*e) < (q+1) |
|---|
| 160 | + -- && q < pw^2 |
|---|
| 161 | + step n pw lg = |
|---|
| 162 | + if n `ltInteger` pw |
|---|
| 163 | + then (# n, 0# #) |
|---|
| 164 | + else case step n (shiftLInteger pw lg) (2# *# lg) of |
|---|
| 165 | + (# q, e #) -> |
|---|
| 166 | + if q `ltInteger` pw |
|---|
| 167 | + then (# q, 2# *# e #) |
|---|
| 168 | + else (# q `shiftRInteger` lg, 2# *# e +# 1# #) |
|---|
| 169 | + |
|---|
| 170 | +integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #) |
|---|
| 171 | +integerLog2IsPowerOf2# m = |
|---|
| 172 | + case integerLog2# m of |
|---|
| 173 | + lg -> if m `eqInteger` (smallInteger 1# `shiftLInteger` lg) |
|---|
| 174 | + then (# lg, 0# #) |
|---|
| 175 | + else (# lg, 1# #) |
|---|
| 176 | + |
|---|
| 177 | +roundingMode# :: Integer -> Int# -> Int# |
|---|
| 178 | +roundingMode# m h = |
|---|
| 179 | + case smallInteger 1# `shiftLInteger` h of |
|---|
| 180 | + c -> case m `andInteger` |
|---|
| 181 | + ((c `plusInteger` c) `minusInteger` smallInteger 1#) of |
|---|
| 182 | + r -> |
|---|
| 183 | + if c `ltInteger` r |
|---|
| 184 | + then 2# |
|---|
| 185 | + else if c `gtInteger` r |
|---|
| 186 | + then 0# |
|---|
| 187 | + else 1# |
|---|
| 188 | + |
|---|
| 189 | +-- Lookup table |
|---|
| 190 | +data BA = BA ByteArray# |
|---|
| 191 | + |
|---|
| 192 | +leadingZeros :: BA |
|---|
| 193 | +leadingZeros = |
|---|
| 194 | + let mkArr s = |
|---|
| 195 | + case newByteArray# 256# s of |
|---|
| 196 | + (# s1, mba #) -> |
|---|
| 197 | + case writeInt8Array# mba 0# 9# s1 of |
|---|
| 198 | + s2 -> |
|---|
| 199 | + let fillA lim val idx st = |
|---|
| 200 | + if idx ==# 256# |
|---|
| 201 | + then st |
|---|
| 202 | + else if idx <# lim |
|---|
| 203 | + then case writeInt8Array# mba idx val st of |
|---|
| 204 | + nx -> fillA lim val (idx +# 1#) nx |
|---|
| 205 | + else fillA (2# *# lim) (val -# 1#) idx st |
|---|
| 206 | + in case fillA 2# 8# 1# s2 of |
|---|
| 207 | + s3 -> case unsafeFreezeByteArray# mba s3 of |
|---|
| 208 | + (# _, ba #) -> ba |
|---|
| 209 | + in case mkArr realWorld# of |
|---|
| 210 | + b -> BA b |
|---|
| 211 | hunk ./integer-simple.cabal 16 |
|---|
| 212 | build-depends: ghc-prim |
|---|
| 213 | exposed-modules: GHC.Integer |
|---|
| 214 | GHC.Integer.Simple.Internals |
|---|
| 215 | + GHC.Integer.Logarithms |
|---|
| 216 | + GHC.Integer.Logarithms.Internals |
|---|
| 217 | other-modules: GHC.Integer.Type |
|---|
| 218 | extensions: CPP, MagicHash, BangPatterns, UnboxedTuples, |
|---|
| 219 | ForeignFunctionInterface, UnliftedFFITypes, |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | Context: |
|---|
| 223 | |
|---|
| 224 | [Follow GHC.Bool/GHC.Types merge |
|---|
| 225 | Ian Lynagh <igloo@earth.li>**20101023153842 |
|---|
| 226 | Ignore-this: eb0bf266cd02a9a11edd84bb0db02b92 |
|---|
| 227 | ] |
|---|
| 228 | [Pad version to 0.1.0.0 |
|---|
| 229 | Ian Lynagh <igloo@earth.li>**20090920141930] |
|---|
| 230 | [Add NoImplicitPrelude to the extensions used |
|---|
| 231 | Ian Lynagh <igloo@earth.li>**20090722174729] |
|---|
| 232 | [Add an import so the deps get sorted out correctly |
|---|
| 233 | Ian Lynagh <igloo@earth.li>**20090722162843] |
|---|
| 234 | [() is now available, so use that instead of our own |
|---|
| 235 | Ian Lynagh <igloo@earth.li>**20090722161829] |
|---|
| 236 | [Follow changes in GHC and the other libraries |
|---|
| 237 | Ian Lynagh <igloo@earth.li>**20090722131507] |
|---|
| 238 | [Fix conversions between Float/Double and simple-integer |
|---|
| 239 | Ian Lynagh <igloo@earth.li>**20080614152452] |
|---|
| 240 | [Sprinkle on some strictness annotations |
|---|
| 241 | Ian Lynagh <igloo@earth.li>**20080602193146] |
|---|
| 242 | [Make the Integer type components strict |
|---|
| 243 | Ian Lynagh <igloo@earth.li>**20080602185149] |
|---|
| 244 | [Avoid the need for infinite Integers when doing bitwise operations |
|---|
| 245 | Ian Lynagh <igloo@earth.li>**20080602184237] |
|---|
| 246 | [Initial commit |
|---|
| 247 | Ian Lynagh <igloo@earth.li>**20080425024824] |
|---|
| 248 | Patch bundle hash: |
|---|
| 249 | b0abc0640f6fa306df1d127dbed7917198b4eab7 |
|---|