Ticket #4344: logarithms-integer-gmp.dpatch

File logarithms-integer-gmp.dpatch, 11.0 KB (added by daniel.is.fischer, 3 years ago)
Line 
11 patch for repository /home/dafis/Haskell/Hacking/ghc/libraries/integer-gmp:
2
3Mon 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
7New patches:
8
9[Logarithms for integer-gmp
10Daniel Fischer <daniel.is.fischer@web.de>**20101025195250
11 Ignore-this: 22e961bde127107d40fcc91f77ba9483
12 Fast integer logarithms as needed for fromRational.
13] {
14adddir ./GHC/Integer/Logarithms
15addfile ./GHC/Integer/Logarithms.hs
16hunk ./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#
62addfile ./GHC/Integer/Logarithms/Internals.hs
63hunk ./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
297hunk ./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
308Context:
309
310[Follow GHC.Bool/GHC.Types merge
311Ian Lynagh <igloo@earth.li>**20101023153631
312 Ignore-this: 4ce6102919eccb7335756bd4001a2322
313]
314[Bump version number to 0.2.0.2
315Ian Lynagh <igloo@earth.li>**20100916170032]
316[Fix compile warning on 32bit machine
317David Terei <davidterei@gmail.com>**20100817103407
318 Ignore-this: 30b715c759d3721a4651c3c94054813
319]
320[fix hashInteger to be the same as fromIntegral, and document it (#4108)
321Simon Marlow <marlowsd@gmail.com>**20100813153142
322 Ignore-this: 5778949a68115bd65464b2b3d4bf4834
323]
324[implement integer2Int# and integer2Word# in Haskell, not foreign prim
325Simon Marlow <marlowsd@gmail.com>**20100813152926
326 Ignore-this: e06beace47751538e72e7b1615ff6dcf
327]
328[Use the stage-specific CONF_CC_OPTS variables
329Ian Lynagh <igloo@earth.li>**20100723135933]
330[TAG Haskell 2010 report generated
331Simon Marlow <marlowsd@gmail.com>**20100705150919
332 Ignore-this: 9e76b0809ef3e0cd86b2dd0efb9c0fb7
333]
334Patch bundle hash:
33593328dc2e5b9a98fdd40cb108cc3a05a9cd63ba0