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