packages feed

bitset-1.4.2: cbits/gmp-extras.cmm

#include "Cmm.h"
#include "GmpDerivedConstants.h"

// TODO(superbobry): in the future release the syntax for calling
// foreign funcations will CHANGE.

import "integer-gmp" __gmpz_init_set;
import "integer-gmp" __gmpz_popcount;
import "integer-gmp" __gmpz_tstbit;
import "integer-gmp" __gmpz_setbit;
import "integer-gmp" __gmpz_clrbit;

#define GMP_TAKE1_UL1_RET1(name,mp_fun)                         \
name                                                            \
{                                                               \
  CInt s;                                                       \
  W_ d;                                                         \
  CLong ul;                                                     \
  W_ mp_tmp;                                                    \
  W_ mp_result;                                                 \
                                                                \
  STK_CHK_GEN(2 * SIZEOF_MP_INT, R2, name);                     \
  MAYBE_GC(R2_PTR, name);                                       \
                                                                \
  s = W_TO_INT(R1);                                             \
  d = R2;                                                       \
  ul = R3;                                                      \
                                                                \
  mp_tmp    = Sp - 1 * SIZEOF_MP_INT;                           \
  mp_result = Sp - 2 * SIZEOF_MP_INT;                           \
  MP_INT__mp_alloc(mp_tmp) = W_TO_INT(BYTE_ARR_WDS(d));         \
  MP_INT__mp_size(mp_tmp)  = (s);                               \
  MP_INT__mp_d(mp_tmp)     = BYTE_ARR_CTS(d);                   \
                                                                \
  foreign "C" __gmpz_init_set(mp_result "ptr", mp_tmp "ptr") [];\
                                                                \
  /* Perform the operation */                                   \
  foreign "C" mp_fun(mp_result "ptr", ul) [];                   \
                                                                \
  RET_NP(TO_W_(MP_INT__mp_size(mp_result)),                     \
         MP_INT__mp_d(mp_result) - SIZEOF_StgArrWords);         \
}

GMP_TAKE1_UL1_RET1(integer_cmm_setBitIntegerzh,   __gmpz_setbit)
GMP_TAKE1_UL1_RET1(integer_cmm_clearBitIntegerzh, __gmpz_clrbit)

integer_cmm_testBitIntegerzh
{
  CInt s, res;
  CLong ul;
  W_ d;
  W_ mp_tmp;

  STK_CHK_GEN(SIZEOF_MP_INT, R2_PTR, integer_cmm_testBitIntegerzh);
  MAYBE_GC(R2_PTR, integer_cmm_testBitIntegerzh);

  s  = W_TO_INT(R1);
  d  = R2;
  ul = R3;

  mp_tmp = Sp - 1 * SIZEOF_MP_INT;
  MP_INT__mp_alloc(mp_tmp) = W_TO_INT(BYTE_ARR_WDS(d));
  MP_INT__mp_size(mp_tmp)  = (s);
  MP_INT__mp_d(mp_tmp)     = BYTE_ARR_CTS(d);

  (res) = foreign "C" __gmpz_tstbit(mp_tmp "ptr", ul) [];

  RET_N(TO_W_(res));
}

integer_cmm_popCountIntegerzh
{
  CInt s, res;
  W_ d;
  W_ mp_tmp;

  STK_CHK_GEN(SIZEOF_MP_INT, R2_PTR, integer_cmm_popCountIntegerzh);
  MAYBE_GC(R2_PTR, integer_cmm_popCountIntegerzh);

  s = W_TO_INT(R1);
  d = R2;

  mp_tmp = Sp - 1 * SIZEOF_MP_INT;
  MP_INT__mp_alloc(mp_tmp) = W_TO_INT(BYTE_ARR_WDS(d));
  MP_INT__mp_size(mp_tmp)  = (s);
  MP_INT__mp_d(mp_tmp)     = BYTE_ARR_CTS(d);

  (res) = foreign "C" __gmpz_popcount(mp_tmp "ptr") [];

  RET_N(TO_W_(res));
}