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