diff options
author | Herbert Valerio Riedel <hvr@gnu.org> | 2013-09-29 10:05:05 +0200 |
---|---|---|
committer | Herbert Valerio Riedel <hvr@gnu.org> | 2013-09-29 18:06:43 +0200 |
commit | 4d516855241b70eb687d95e3c121428de885e83e (patch) | |
tree | 4484648a1ba4b58ee8a30116fa7f4d458cbf0ea9 /libraries/integer-gmp/cbits | |
parent | 345c31648808d4784d5a65ca5168a05eb5f8ffbc (diff) | |
download | haskell-4d516855241b70eb687d95e3c121428de885e83e.tar.gz |
Expose new internal exponentiation primitives
This exposes the GMP functions `mpz_pow_ui()`, `mpz_powm()`, and
`mpz_invert()` as `powInteger`, `powModInteger`, and `recipModInteger`
respectively in the module `GHC.Integer.GMP.Internals`.
Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org>
Diffstat (limited to 'libraries/integer-gmp/cbits')
-rw-r--r-- | libraries/integer-gmp/cbits/gmp-wrappers.cmm | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/libraries/integer-gmp/cbits/gmp-wrappers.cmm b/libraries/integer-gmp/cbits/gmp-wrappers.cmm index 8a201f12d0..5c7bb0b725 100644 --- a/libraries/integer-gmp/cbits/gmp-wrappers.cmm +++ b/libraries/integer-gmp/cbits/gmp-wrappers.cmm @@ -49,6 +49,9 @@ import "integer-gmp" __gmpz_and; import "integer-gmp" __gmpz_xor; import "integer-gmp" __gmpz_ior; import "integer-gmp" __gmpz_com; +import "integer-gmp" __gmpz_pow_ui; +import "integer-gmp" __gmpz_powm; +import "integer-gmp" __gmpz_invert; import "integer-gmp" integer_cbits_decodeDouble; @@ -246,6 +249,47 @@ again: \ MP_INT__mp_d(mp_result1) - SIZEOF_StgArrWords); \ } +#define GMP_TAKE3_RET1(name,mp_fun) \ +name (W_ ws1, P_ d1, W_ ws2, P_ d2, W_ ws3, P_ d3) \ +{ \ + CInt s1, s2, s3; \ + W_ mp_tmp1; \ + W_ mp_tmp2; \ + W_ mp_tmp3; \ + W_ mp_result1; \ + \ +again: \ + STK_CHK_GEN_N (4 * SIZEOF_MP_INT); \ + MAYBE_GC(again); \ + \ + s1 = W_TO_INT(ws1); \ + s2 = W_TO_INT(ws2); \ + s3 = W_TO_INT(ws3); \ + \ + mp_tmp1 = Sp - 1 * SIZEOF_MP_INT; \ + mp_tmp2 = Sp - 2 * SIZEOF_MP_INT; \ + mp_tmp3 = Sp - 3 * SIZEOF_MP_INT; \ + mp_result1 = Sp - 4 * SIZEOF_MP_INT; \ + MP_INT__mp_alloc(mp_tmp1) = W_TO_INT(BYTE_ARR_WDS(d1)); \ + MP_INT__mp_size(mp_tmp1) = (s1); \ + MP_INT__mp_d(mp_tmp1) = BYTE_ARR_CTS(d1); \ + MP_INT__mp_alloc(mp_tmp2) = W_TO_INT(BYTE_ARR_WDS(d2)); \ + MP_INT__mp_size(mp_tmp2) = (s2); \ + MP_INT__mp_d(mp_tmp2) = BYTE_ARR_CTS(d2); \ + MP_INT__mp_alloc(mp_tmp3) = W_TO_INT(BYTE_ARR_WDS(d3)); \ + MP_INT__mp_size(mp_tmp3) = (s3); \ + MP_INT__mp_d(mp_tmp3) = BYTE_ARR_CTS(d3); \ + \ + ccall __gmpz_init(mp_result1 "ptr"); \ + \ + /* Perform the operation */ \ + ccall mp_fun(mp_result1 "ptr",mp_tmp1 "ptr",mp_tmp2 "ptr", \ + mp_tmp3 "ptr"); \ + \ + return (TO_W_(MP_INT__mp_size(mp_result1)), \ + MP_INT__mp_d(mp_result1) - SIZEOF_StgArrWords); \ +} + #define GMP_TAKE1_UL1_RET1(name,mp_fun) \ name (W_ ws1, P_ d1, W_ wul) \ { \ @@ -389,6 +433,10 @@ GMP_TAKE1_RET1(integer_cmm_complementIntegerzh, __gmpz_com) GMP_TAKE2_RET2(integer_cmm_quotRemIntegerzh, __gmpz_tdiv_qr) GMP_TAKE2_RET2(integer_cmm_divModIntegerzh, __gmpz_fdiv_qr) +GMP_TAKE3_RET1(integer_cmm_powModIntegerzh, __gmpz_powm) +GMP_TAKE2_RET1(integer_cmm_recipModIntegerzh, __gmpz_invert) +GMP_TAKE1_UL1_RET1(integer_cmm_powIntegerzh, __gmpz_pow_ui) + integer_cmm_gcdIntzh (W_ int1, W_ int2) { W_ r; |