Expose new internal exponentiation primitives
[packages/integer-gmp.git] / GHC / Integer / GMP / Prim.hs
1 {-# LANGUAGE ForeignFunctionInterface, GHCForeignImportPrim, CPP,
2 MagicHash, UnboxedTuples, UnliftedFFITypes, BangPatterns #-}
3 {-# OPTIONS_GHC -XNoImplicitPrelude #-}
4 {-# OPTIONS_HADDOCK hide #-}
5
6 #include "MachDeps.h"
7 module GHC.Integer.GMP.Prim (
8 cmpInteger#,
9 cmpIntegerInt#,
10
11 plusInteger#,
12 minusInteger#,
13 timesInteger#,
14
15 quotRemInteger#,
16 quotInteger#,
17 remInteger#,
18 divModInteger#,
19 divInteger#,
20 modInteger#,
21 divExactInteger#,
22
23 gcdInteger#,
24 gcdIntegerInt#,
25 gcdInt#,
26
27 decodeDouble#,
28
29 int2Integer#,
30 integer2Int#,
31
32 word2Integer#,
33 integer2Word#,
34
35 andInteger#,
36 orInteger#,
37 xorInteger#,
38 complementInteger#,
39
40 testBitInteger#,
41 mul2ExpInteger#,
42 fdivQ2ExpInteger#,
43
44 powInteger#,
45 powModInteger#,
46 recipModInteger#,
47
48 #if WORD_SIZE_IN_BITS < 64
49 int64ToInteger#, integerToInt64#,
50 word64ToInteger#, integerToWord64#,
51 #endif
52
53 #ifndef WORD_SIZE_IN_BITS
54 #error WORD_SIZE_IN_BITS not defined!!!
55 #endif
56
57 ) where
58
59 import GHC.Prim
60 import GHC.Types
61
62 -- Double isn't available yet, and we shouldn't be using defaults anyway:
63 default ()
64
65 -- | Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument.
66 --
67 foreign import prim "integer_cmm_cmpIntegerzh" cmpInteger#
68 :: Int# -> ByteArray# -> Int# -> ByteArray# -> Int#
69
70 -- | Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument, which
71 -- is an ordinary Int\#.
72 foreign import prim "integer_cmm_cmpIntegerIntzh" cmpIntegerInt#
73 :: Int# -> ByteArray# -> Int# -> Int#
74
75 -- |
76 --
77 foreign import prim "integer_cmm_plusIntegerzh" plusInteger#
78 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
79
80 -- |
81 --
82 foreign import prim "integer_cmm_minusIntegerzh" minusInteger#
83 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
84
85 -- |
86 --
87 foreign import prim "integer_cmm_timesIntegerzh" timesInteger#
88 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
89
90 -- | Compute div and mod simultaneously, where div rounds towards negative
91 -- infinity and\ @(q,r) = divModInteger#(x,y)@ implies
92 -- @plusInteger# (timesInteger# q y) r = x@.
93 --
94 foreign import prim "integer_cmm_quotRemIntegerzh" quotRemInteger#
95 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
96
97 -- | Rounds towards zero.
98 --
99 foreign import prim "integer_cmm_quotIntegerzh" quotInteger#
100 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
101
102 -- | Satisfies \texttt{plusInteger\# (timesInteger\# (quotInteger\# x y) y) (remInteger\# x y) == x}.
103 --
104 foreign import prim "integer_cmm_remIntegerzh" remInteger#
105 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
106
107 -- | Compute div and mod simultaneously, where div rounds towards negative infinity
108 -- and\texttt{(q,r) = divModInteger\#(x,y)} implies \texttt{plusInteger\# (timesInteger\# q y) r = x}.
109 --
110 foreign import prim "integer_cmm_divModIntegerzh" divModInteger#
111 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
112 foreign import prim "integer_cmm_divIntegerzh" divInteger#
113 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
114 foreign import prim "integer_cmm_modIntegerzh" modInteger#
115 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
116
117 -- | Divisor is guaranteed to be a factor of dividend.
118 --
119 foreign import prim "integer_cmm_divExactIntegerzh" divExactInteger#
120 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
121
122 -- | Greatest common divisor.
123 --
124 foreign import prim "integer_cmm_gcdIntegerzh" gcdInteger#
125 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
126
127 -- | Greatest common divisor, where second argument is an ordinary {\tt Int\#}.
128 --
129 foreign import prim "integer_cmm_gcdIntegerIntzh" gcdIntegerInt#
130 :: Int# -> ByteArray# -> Int# -> Int#
131
132 -- |
133 --
134 foreign import prim "integer_cmm_gcdIntzh" gcdInt#
135 :: Int# -> Int# -> Int#
136
137 -- | Convert to arbitrary-precision integer.
138 -- First {\tt Int\#} in result is the exponent; second {\tt Int\#} and {\tt ByteArray\#}
139 -- represent an {\tt Integer\#} holding the mantissa.
140 --
141 foreign import prim "integer_cmm_decodeDoublezh" decodeDouble#
142 :: Double# -> (# Int#, Int#, ByteArray# #)
143
144 -- |
145 --
146 foreign import prim "integer_cmm_int2Integerzh" int2Integer#
147 :: Int# -> (# Int#, ByteArray# #)
148
149 -- |
150 --
151 foreign import prim "integer_cmm_word2Integerzh" word2Integer#
152 :: Word# -> (# Int#, ByteArray# #)
153
154 -- |
155 --
156 foreign import prim "integer_cmm_andIntegerzh" andInteger#
157 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
158
159 -- |
160 --
161 foreign import prim "integer_cmm_orIntegerzh" orInteger#
162 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
163
164 -- |
165 --
166 foreign import prim "integer_cmm_xorIntegerzh" xorInteger#
167 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
168
169 -- |
170 --
171 foreign import prim "integer_cmm_testBitIntegerzh" testBitInteger#
172 :: Int# -> ByteArray# -> Int# -> Int#
173
174 -- |
175 --
176 foreign import prim "integer_cmm_mul2ExpIntegerzh" mul2ExpInteger#
177 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
178
179 -- |
180 --
181 foreign import prim "integer_cmm_fdivQ2ExpIntegerzh" fdivQ2ExpInteger#
182 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
183
184 -- |
185 --
186 foreign import prim "integer_cmm_powIntegerzh" powInteger#
187 :: Int# -> ByteArray# -> Word# -> (# Int#, ByteArray# #)
188
189 -- |
190 --
191 foreign import prim "integer_cmm_powModIntegerzh" powModInteger#
192 :: Int# -> ByteArray# -> Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
193
194 -- |
195 --
196 foreign import prim "integer_cmm_recipModIntegerzh" recipModInteger#
197 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
198
199 -- |
200 --
201 foreign import prim "integer_cmm_complementIntegerzh" complementInteger#
202 :: Int# -> ByteArray# -> (# Int#, ByteArray# #)
203
204 #if WORD_SIZE_IN_BITS < 64
205 foreign import prim "integer_cmm_int64ToIntegerzh" int64ToInteger#
206 :: Int64# -> (# Int#, ByteArray# #)
207
208 foreign import prim "integer_cmm_word64ToIntegerzh" word64ToInteger#
209 :: Word64# -> (# Int#, ByteArray# #)
210
211 foreign import ccall unsafe "hs_integerToInt64"
212 integerToInt64# :: Int# -> ByteArray# -> Int64#
213
214 foreign import ccall unsafe "hs_integerToWord64"
215 integerToWord64# :: Int# -> ByteArray# -> Word64#
216 #endif
217
218 -- used to be primops:
219 integer2Int# :: Int# -> ByteArray# -> Int#
220 integer2Int# s d = if isTrue# (s ==# 0#)
221 then 0#
222 else let !v = indexIntArray# d 0# in
223 if isTrue# (s <# 0#)
224 then negateInt# v
225 else v
226
227 integer2Word# :: Int# -> ByteArray# -> Word#
228 integer2Word# s d = int2Word# (integer2Int# s d)