Add divInteger and modInteger functions
[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 mul2ExpInteger#,
41 fdivQ2ExpInteger#,
42
43 #if WORD_SIZE_IN_BITS < 64
44 int64ToInteger#, integerToInt64#,
45 word64ToInteger#, integerToWord64#,
46 #endif
47
48 #ifndef WORD_SIZE_IN_BITS
49 #error WORD_SIZE_IN_BITS not defined!!!
50 #endif
51
52 ) where
53
54 import GHC.Prim
55
56 -- Double isn't available yet, and we shouldn't be using defaults anyway:
57 default ()
58
59 -- | Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument.
60 --
61 foreign import prim "integer_cmm_cmpIntegerzh" cmpInteger#
62 :: Int# -> ByteArray# -> Int# -> ByteArray# -> Int#
63
64 -- | Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument, which
65 -- is an ordinary Int\#.
66 foreign import prim "integer_cmm_cmpIntegerIntzh" cmpIntegerInt#
67 :: Int# -> ByteArray# -> Int# -> Int#
68
69 -- |
70 --
71 foreign import prim "integer_cmm_plusIntegerzh" plusInteger#
72 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
73
74 -- |
75 --
76 foreign import prim "integer_cmm_minusIntegerzh" minusInteger#
77 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
78
79 -- |
80 --
81 foreign import prim "integer_cmm_timesIntegerzh" timesInteger#
82 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
83
84 -- | Compute div and mod simultaneously, where div rounds towards negative
85 -- infinity and\ @(q,r) = divModInteger#(x,y)@ implies
86 -- @plusInteger# (timesInteger# q y) r = x@.
87 --
88 foreign import prim "integer_cmm_quotRemIntegerzh" quotRemInteger#
89 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
90
91 -- | Rounds towards zero.
92 --
93 foreign import prim "integer_cmm_quotIntegerzh" quotInteger#
94 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
95
96 -- | Satisfies \texttt{plusInteger\# (timesInteger\# (quotInteger\# x y) y) (remInteger\# x y) == x}.
97 --
98 foreign import prim "integer_cmm_remIntegerzh" remInteger#
99 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
100
101 -- | Compute div and mod simultaneously, where div rounds towards negative infinity
102 -- and\texttt{(q,r) = divModInteger\#(x,y)} implies \texttt{plusInteger\# (timesInteger\# q y) r = x}.
103 --
104 foreign import prim "integer_cmm_divModIntegerzh" divModInteger#
105 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
106 foreign import prim "integer_cmm_divIntegerzh" divInteger#
107 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
108 foreign import prim "integer_cmm_modIntegerzh" modInteger#
109 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
110
111 -- | Divisor is guaranteed to be a factor of dividend.
112 --
113 foreign import prim "integer_cmm_divExactIntegerzh" divExactInteger#
114 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
115
116 -- | Greatest common divisor.
117 --
118 foreign import prim "integer_cmm_gcdIntegerzh" gcdInteger#
119 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
120
121 -- | Greatest common divisor, where second argument is an ordinary {\tt Int\#}.
122 --
123 foreign import prim "integer_cmm_gcdIntegerIntzh" gcdIntegerInt#
124 :: Int# -> ByteArray# -> Int# -> Int#
125
126 -- |
127 --
128 foreign import prim "integer_cmm_gcdIntzh" gcdInt#
129 :: Int# -> Int# -> Int#
130
131 -- | Convert to arbitrary-precision integer.
132 -- First {\tt Int\#} in result is the exponent; second {\tt Int\#} and {\tt ByteArray\#}
133 -- represent an {\tt Integer\#} holding the mantissa.
134 --
135 foreign import prim "integer_cmm_decodeDoublezh" decodeDouble#
136 :: Double# -> (# Int#, Int#, ByteArray# #)
137
138 -- |
139 --
140 foreign import prim "integer_cmm_int2Integerzh" int2Integer#
141 :: Int# -> (# Int#, ByteArray# #)
142
143 -- |
144 --
145 foreign import prim "integer_cmm_word2Integerzh" word2Integer#
146 :: Word# -> (# Int#, ByteArray# #)
147
148 -- |
149 --
150 foreign import prim "integer_cmm_andIntegerzh" andInteger#
151 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
152
153 -- |
154 --
155 foreign import prim "integer_cmm_orIntegerzh" orInteger#
156 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
157
158 -- |
159 --
160 foreign import prim "integer_cmm_xorIntegerzh" xorInteger#
161 :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
162
163 -- |
164 --
165 foreign import prim "integer_cmm_mul2ExpIntegerzh" mul2ExpInteger#
166 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
167
168 -- |
169 --
170 foreign import prim "integer_cmm_fdivQ2ExpIntegerzh" fdivQ2ExpInteger#
171 :: Int# -> ByteArray# -> Int# -> (# Int#, ByteArray# #)
172
173 -- |
174 --
175 foreign import prim "integer_cmm_complementIntegerzh" complementInteger#
176 :: Int# -> ByteArray# -> (# Int#, ByteArray# #)
177
178 #if WORD_SIZE_IN_BITS < 64
179 foreign import prim "integer_cmm_int64ToIntegerzh" int64ToInteger#
180 :: Int64# -> (# Int#, ByteArray# #)
181
182 foreign import prim "integer_cmm_word64ToIntegerzh" word64ToInteger#
183 :: Word64# -> (# Int#, ByteArray# #)
184
185 foreign import ccall unsafe "hs_integerToInt64"
186 integerToInt64# :: Int# -> ByteArray# -> Int64#
187
188 foreign import ccall unsafe "hs_integerToWord64"
189 integerToWord64# :: Int# -> ByteArray# -> Word64#
190 #endif
191
192 -- used to be primops:
193 integer2Int# :: Int# -> ByteArray# -> Int#
194 integer2Int# s d = if s ==# 0#
195 then 0#
196 else let !v = indexIntArray# d 0# in
197 if s <# 0#
198 then negateInt# v
199 else v
200
201 integer2Word# :: Int# -> ByteArray# -> Word#
202 integer2Word# s d = int2Word# (integer2Int# s d)