Add new `mpz_mul_si`-based primop (re #8647)
[ghc.git] / libraries / integer-gmp / GHC / Integer / GMP / Prim.hs
1 {-# LANGUAGE BangPatterns, CPP, MagicHash, NoImplicitPrelude, UnboxedTuples
2 , UnliftedFFITypes, GHCForeignImportPrim #-}
3 {-# OPTIONS_HADDOCK hide #-}
4
5 #include "MachDeps.h"
6 module GHC.Integer.GMP.Prim (
7 cmpInteger#,
8 cmpIntegerInt#,
9
10 plusInteger#,
11 minusInteger#,
12 timesInteger#,
13 timesIntegerInt#,
14
15 quotRemInteger#,
16 quotInteger#,
17 remInteger#,
18 divModInteger#,
19 divInteger#,
20 modInteger#,
21 divExactInteger#,
22
23 gcdInteger#,
24 gcdExtInteger#,
25 gcdIntegerInt#,
26 gcdInt#,
27
28 decodeDouble#,
29
30 int2Integer#,
31 integer2Int#,
32
33 word2Integer#,
34 integer2Word#,
35
36 andInteger#,
37 orInteger#,
38 xorInteger#,
39 complementInteger#,
40
41 testBitInteger#,
42 mul2ExpInteger#,
43 fdivQ2ExpInteger#,
44
45 powInteger#,
46 powModInteger#,
47 powModSecInteger#,
48 recipModInteger#,
49
50 nextPrimeInteger#,
51 testPrimeInteger#,
52
53 sizeInBaseInteger#,
54 importIntegerFromByteArray#,
55 importIntegerFromAddr#,
56 exportIntegerToMutableByteArray#,
57 exportIntegerToAddr#,
58
59 #if WORD_SIZE_IN_BITS < 64
60 int64ToInteger#, integerToInt64#,
61 word64ToInteger#, integerToWord64#,
62 #endif
63
64 #ifndef WORD_SIZE_IN_BITS
65 #error WORD_SIZE_IN_BITS not defined!!!
66 #endif
67
68 ) where
69
70 import GHC.Prim
71 import GHC.Types
72
73 -- Double isn't available yet, and we shouldn't be using defaults anyway:
74 default ()
75
76 -- | Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument.
77 --
78 foreign import prim "integer_cmm_cmpIntegerzh" cmpInteger#
79 :: Int# -> ByteArray# -> Int# -> ByteArray# -> Int#
80
81 -- | Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument, which
82 -- is an ordinary Int\#.
83 foreign import prim "integer_cmm_cmpIntegerIntzh" cmpIntegerInt#
84 :: Int# -> ByteArray# -> Int# -> Int#
85
86 -- |
87 --
88 foreign import prim "integer_cmm_plusIntegerzh" plusInteger#
89 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
90
91 -- |
92 --
93 foreign import prim "integer_cmm_minusIntegerzh" minusInteger#
94 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
95
96 -- |
97 --
98 foreign import prim "integer_cmm_timesIntegerzh" timesInteger#
99 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
100
101 -- | Optimized version of 'timesInteger#' for multiplying big-ints with small-ints
102 --
103 foreign import prim "integer_cmm_timesIntegerIntzh" timesIntegerInt#
104 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
105
106 -- | Compute div and mod simultaneously, where div rounds towards negative
107 -- infinity and\ @(q,r) = divModInteger#(x,y)@ implies
108 -- @plusInteger# (timesInteger# q y) r = x@.
109 --
110 foreign import prim "integer_cmm_quotRemIntegerzh" quotRemInteger#
111 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
112
113 -- | Rounds towards zero.
114 --
115 foreign import prim "integer_cmm_quotIntegerzh" quotInteger#
116 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
117
118 -- | Satisfies \texttt{plusInteger\# (timesInteger\# (quotInteger\# x y) y) (remInteger\# x y) == x}.
119 --
120 foreign import prim "integer_cmm_remIntegerzh" remInteger#
121 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
122
123 -- | Compute div and mod simultaneously, where div rounds towards negative infinity
124 -- and\texttt{(q,r) = divModInteger\#(x,y)} implies \texttt{plusInteger\# (timesInteger\# q y) r = x}.
125 --
126 foreign import prim "integer_cmm_divModIntegerzh" divModInteger#
127 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
128 foreign import prim "integer_cmm_divIntegerzh" divInteger#
129 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
130 foreign import prim "integer_cmm_modIntegerzh" modInteger#
131 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
132
133 -- | Divisor is guaranteed to be a factor of dividend.
134 --
135 foreign import prim "integer_cmm_divExactIntegerzh" divExactInteger#
136 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
137
138 -- | Greatest common divisor.
139 --
140 foreign import prim "integer_cmm_gcdIntegerzh" gcdInteger#
141 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
142
143 -- | Extended greatest common divisor.
144 --
145 foreign import prim "integer_cmm_gcdExtIntegerzh" gcdExtInteger#
146 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
147
148 -- | Greatest common divisor, where second argument is an ordinary {\tt Int\#}.
149 --
150 foreign import prim "integer_cmm_gcdIntegerIntzh" gcdIntegerInt#
151 :: Int# -> ByteArray# -> Int# -> Int#
152
153 -- |
154 --
155 foreign import prim "integer_cmm_gcdIntzh" gcdInt#
156 :: Int# -> Int# -> Int#
157
158 -- | Convert to arbitrary-precision integer.
159 -- First {\tt Int\#} in result is the exponent; second {\tt Int\#} and {\tt ByteArray\#}
160 -- represent an {\tt Integer\#} holding the mantissa.
161 --
162 foreign import prim "integer_cmm_decodeDoublezh" decodeDouble#
163 :: Double# -> (# Int#, Int#, ByteArray# #)
164
165 -- |
166 --
167 foreign import prim "integer_cmm_int2Integerzh" int2Integer#
168 :: Int# -> (# Int#, ByteArray# #)
169
170 -- |
171 --
172 foreign import prim "integer_cmm_word2Integerzh" word2Integer#
173 :: Word# -> (# Int#, ByteArray# #)
174
175 -- |
176 --
177 foreign import prim "integer_cmm_andIntegerzh" andInteger#
178 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
179
180 -- |
181 --
182 foreign import prim "integer_cmm_orIntegerzh" orInteger#
183 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
184
185 -- |
186 --
187 foreign import prim "integer_cmm_xorIntegerzh" xorInteger#
188 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
189
190 -- |
191 --
192 foreign import prim "integer_cmm_testBitIntegerzh" testBitInteger#
193 :: Int# -> ByteArray# -> Int# -> Int#
194
195 -- |
196 --
197 foreign import prim "integer_cmm_mul2ExpIntegerzh" mul2ExpInteger#
198 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
199
200 -- |
201 --
202 foreign import prim "integer_cmm_fdivQ2ExpIntegerzh" fdivQ2ExpInteger#
203 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
204
205 -- |
206 --
207 foreign import prim "integer_cmm_powIntegerzh" powInteger#
208 :: Int# -> ByteArray# -> Word# -> (# Int#, ByteArray# #)
209
210 -- |
211 --
212 foreign import prim "integer_cmm_powModIntegerzh" powModInteger#
213 :: Int# -> ByteArray# -> Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
214
215 -- |
216 --
217 foreign import prim "integer_cmm_powModSecIntegerzh" powModSecInteger#
218 :: Int# -> ByteArray# -> Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
219
220 -- |
221 --
222 foreign import prim "integer_cmm_recipModIntegerzh" recipModInteger#
223 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
224
225 -- |
226 --
227 foreign import prim "integer_cmm_nextPrimeIntegerzh" nextPrimeInteger#
228 :: Int# -> ByteArray# -> (# Int#, ByteArray# #)
229
230 -- |
231 --
232 foreign import prim "integer_cmm_testPrimeIntegerzh" testPrimeInteger#
233 :: Int# -> ByteArray# -> Int# -> Int#
234
235 -- |
236 --
237 foreign import prim "integer_cmm_sizeInBasezh" sizeInBaseInteger#
238 :: Int# -> ByteArray# -> Int# -> Word#
239
240 -- |
241 --
242 foreign import prim "integer_cmm_importIntegerFromByteArrayzh" importIntegerFromByteArray#
243 :: ByteArray# -> Word# -> Word# -> Int# -> (# Int#, ByteArray# #)
244
245 -- |
246 --
247 foreign import prim "integer_cmm_importIntegerFromAddrzh" importIntegerFromAddr#
248 :: Addr# -> Word# -> Int# -> State# s -> (# State# s, Int#, ByteArray# #)
249
250 -- |
251 --
252 foreign import prim "integer_cmm_exportIntegerToMutableByteArrayzh" exportIntegerToMutableByteArray#
253 :: Int# -> ByteArray# -> MutableByteArray# s -> Word# -> Int# -> State# s -> (# State# s, Word# #)
254
255 -- |
256 --
257 foreign import prim "integer_cmm_exportIntegerToAddrzh" exportIntegerToAddr#
258 :: Int# -> ByteArray# -> Addr# -> Int# -> State# s -> (# State# s, Word# #)
259
260 -- |
261 --
262 foreign import prim "integer_cmm_complementIntegerzh" complementInteger#
263 :: Int# -> ByteArray# -> (# Int#, ByteArray# #)
264
265 #if WORD_SIZE_IN_BITS < 64
266 foreign import prim "integer_cmm_int64ToIntegerzh" int64ToInteger#
267 :: Int64# -> (# Int#, ByteArray# #)
268
269 foreign import prim "integer_cmm_word64ToIntegerzh" word64ToInteger#
270 :: Word64# -> (# Int#, ByteArray# #)
271
272 foreign import ccall unsafe "hs_integerToInt64"
273 integerToInt64# :: Int# -> ByteArray# -> Int64#
274
275 foreign import ccall unsafe "hs_integerToWord64"
276 integerToWord64# :: Int# -> ByteArray# -> Word64#
277 #endif
278
279 -- used to be primops:
280 integer2Int# :: Int# -> ByteArray# -> Int#
281 integer2Int# s d = if isTrue# (s ==# 0#)
282 then 0#
283 else let !v = indexIntArray# d 0# in
284 if isTrue# (s <# 0#)
285 then negateInt# v
286 else v
287
288 integer2Word# :: Int# -> ByteArray# -> Word#
289 integer2Word# s d = int2Word# (integer2Int# s d)