summaryrefslogtreecommitdiff
path: root/libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2015-03-29 19:02:08 +0200
committerHerbert Valerio Riedel <hvr@gnu.org>2015-03-31 10:59:36 +0200
commit995e8c1c8692b60c907c7d2ccea179d52ca8e69e (patch)
tree1314ec36672d72b33a99b33e017316c0b8585625 /libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs
parent1f69f37f34c6f15fd900c2c1cce3ce896168dde9 (diff)
downloadhaskell-995e8c1c8692b60c907c7d2ccea179d52ca8e69e.tar.gz
Drop old integer-gmp-0.5 from GHC source tree
This completes what c774b28f76ee4c220f7c1c9fd81585e0e3af0e8a (#9281) started. `integer-gmp-1.0` was added as an additional `libraries/integer-gmp2` folder while retaining the ability to configure GHC w/ the old `integer-gmp-0.5` to have a way back, and or the ability to easily switch between old/new `integer-gmp` for benchmark/debugging purposes. This commit removes the old `libraries/integer-gmp` folder and moves `libraries/integer-gmp2` into its place, while removing any mentions of "gmp2" as well as the to support two different `integer-gmp` packages in GHC's source-tree. Reviewed By: austin Differential Revision: https://phabricator.haskell.org/D769
Diffstat (limited to 'libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs')
-rw-r--r--libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs118
1 files changed, 118 insertions, 0 deletions
diff --git a/libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs b/libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs
new file mode 100644
index 0000000000..7ac3645c74
--- /dev/null
+++ b/libraries/integer-gmp/src/GHC/Integer/Logarithms/Internals.hs
@@ -0,0 +1,118 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_HADDOCK hide #-}
+
+#include "MachDeps.h"
+
+#if WORD_SIZE_IN_BITS == 32
+# define WSHIFT 5
+# define MMASK 31
+#elif WORD_SIZE_IN_BITS == 64
+# define WSHIFT 6
+# define MMASK 63
+#else
+# error unsupported WORD_SIZE_IN_BITS
+#endif
+
+-- | Fast 'Integer' logarithms to base 2. 'integerLog2#' and
+-- 'wordLog2#' are of general usefulness, the others are only needed
+-- for a fast implementation of 'fromRational'. Since they are needed
+-- in "GHC.Float", we must expose this module, but it should not show
+-- up in the docs.
+--
+-- See https://ghc.haskell.org/trac/ghc/ticket/5122
+-- for the origin of the code in this module
+module GHC.Integer.Logarithms.Internals
+ ( wordLog2#
+ , integerLog2IsPowerOf2#
+ , integerLog2#
+ , roundingMode#
+ ) where
+
+import GHC.Integer.Type
+import GHC.Integer.Logarithms
+
+import GHC.Types
+import GHC.Prim
+
+default ()
+
+-- | Extended version of 'integerLog2#'
+--
+-- Assumption: Integer is strictly positive
+--
+-- First component of result is @log2 n@, second is @0#@ iff /n/ is a
+-- power of two.
+integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #)
+-- The power of 2 test is n&(n-1) == 0, thus powers of 2
+-- are indicated bythe second component being zero.
+integerLog2IsPowerOf2# (S# i#) = case int2Word# i# of
+ w -> (# wordLog2# w, word2Int# (w `and#` (w `minusWord#` 1##)) #)
+integerLog2IsPowerOf2# (Jn# _) = (# -1#, -1# #)
+-- Find the log2 as above, test whether that word is a power
+-- of 2, if so, check whether only zero bits follow.
+integerLog2IsPowerOf2# (Jp# bn) = check (s -# 1#)
+ where
+ s = sizeofBigNat# bn
+ check :: Int# -> (# Int#, Int# #)
+ check i = case indexBigNat# bn i of
+ 0## -> check (i -# 1#)
+ w -> (# wordLog2# w +# (uncheckedIShiftL# i WSHIFT#)
+ , case w `and#` (w `minusWord#` 1##) of
+ 0## -> test (i -# 1#)
+ _ -> 1# #)
+ test :: Int# -> Int#
+ test i = if isTrue# (i <# 0#)
+ then 0#
+ else case indexBigNat# bn i of
+ 0## -> test (i -# 1#)
+ _ -> 1#
+
+
+-- Assumption: Integer and Int# are strictly positive, Int# is less
+-- than logBase 2 of Integer, otherwise havoc ensues.
+-- Used only for the numerator in fromRational when the denominator
+-- is a power of 2.
+-- The Int# argument is log2 n minus the number of bits in the mantissa
+-- of the target type, i.e. the index of the first non-integral bit in
+-- the quotient.
+--
+-- 0# means round down (towards zero)
+-- 1# means we have a half-integer, round to even
+-- 2# means round up (away from zero)
+roundingMode# :: Integer -> Int# -> Int#
+roundingMode# (S# i#) t =
+ case int2Word# i# `and#` ((uncheckedShiftL# 2## t) `minusWord#` 1##) of
+ k -> case uncheckedShiftL# 1## t of
+ c -> if isTrue# (c `gtWord#` k)
+ then 0#
+ else if isTrue# (c `ltWord#` k)
+ then 2#
+ else 1#
+
+roundingMode# (Jn# bn) t = roundingMode# (Jp# bn) t -- dummy
+roundingMode# (Jp# bn) t =
+ case word2Int# (int2Word# t `and#` MMASK##) of
+ j -> -- index of relevant bit in word
+ case uncheckedIShiftRA# t WSHIFT# of
+ k -> -- index of relevant word
+ case indexBigNat# bn k `and#`
+ ((uncheckedShiftL# 2## j) `minusWord#` 1##) of
+ r ->
+ case uncheckedShiftL# 1## j of
+ c -> if isTrue# (c `gtWord#` r)
+ then 0#
+ else if isTrue# (c `ltWord#` r)
+
+
+ then 2#
+ else test (k -# 1#)
+ where
+ test i = if isTrue# (i <# 0#)
+ then 1#
+ else case indexBigNat# bn i of
+ 0## -> test (i -# 1#)
+ _ -> 2#