Beispiel #1
0
void
mpq_set_ui (MP_RAT *dest, unsigned long int num, unsigned long int den)
{
  if (GMP_NUMB_BITS < BITS_PER_ULONG)
    {
      if (num == 0)  /* Canonicalize 0/d to 0/1.  */
        den = 1;
      mpz_set_ui (mpq_numref (dest), num);
      mpz_set_ui (mpq_denref (dest), den);
      return;
    }

  if (num == 0)
    {
      /* Canonicalize 0/n to 0/1.  */
      den = 1;
      SIZ(NUM(dest)) = 0;
    }
  else
    {
      PTR(NUM(dest))[0] = num;
      SIZ(NUM(dest)) = 1;
    }

  PTR(DEN(dest))[0] = den;
  SIZ(DEN(dest)) = (den != 0);
}
Beispiel #2
0
int
_mpq_cmp_si (mpq_srcptr q, long n, unsigned long d)
{
  /* need canonical sign to get right result */
  ASSERT (SIZ(DEN(q)) > 0);

  if (SIZ(NUM(q)) >= 0)
    {
      if (n >= 0)
        return _mpq_cmp_ui (q, n, d);            /* >=0 cmp >=0 */
      else
        return 1;                                /* >=0 cmp <0 */
    }
  else
    {
      if (n >= 0)
        return -1;                               /* <0 cmp >=0 */
      else
        {
          mpq_t  qabs;
          SIZ(NUM(qabs)) = ABSIZ(NUM(q));
          PTR(NUM(qabs)) = PTR(NUM(q));
          SIZ(DEN(qabs)) = SIZ(DEN(q));
          PTR(DEN(qabs)) = PTR(DEN(q));

          return - _mpq_cmp_ui (qabs, NEG_CAST (unsigned long, n), d);    /* <0 cmp <0 */
        }
    }
}
Beispiel #3
0
void
mpq_clear (mpq_t m)
{
  (*__gmp_free_func) (PTR(NUM(m)),
		    (size_t) ALLOC(NUM(m)) * GMP_LIMB_BYTES);
  (*__gmp_free_func) (PTR(DEN(m)),
		    (size_t) ALLOC(DEN(m)) * GMP_LIMB_BYTES);
}
Beispiel #4
0
void
mpq_clear (MP_RAT *m)
{
  (*__gmp_free_func) (PTR(NUM(m)),
		    ALLOC(NUM(m)) * BYTES_PER_MP_LIMB);
  (*__gmp_free_func) (PTR(DEN(m)),
		    ALLOC(DEN(m)) * BYTES_PER_MP_LIMB);
}
Beispiel #5
0
void
mpq_set_den (mpq_ptr dest, mpz_srcptr den)
{
  mp_size_t size = SIZ (den);
  mp_size_t abs_size = ABS (size);
  mp_ptr dp;

  dp = MPZ_NEWALLOC (DEN(dest), abs_size);

  SIZ(DEN(dest)) = size;
  MPN_COPY (dp, PTR(den), abs_size);
}
Beispiel #6
0
void ssi_init(ssi_ports_e ssi_index, bool config_fss_pin)
{
    if (ssi_index >= SSI_MAX)
        return;      
     
    SYSCTL_RCGCGPIO_R |= ssi_pins_data[ssi_index].port_clock_enable_bit;
    SYSCTL_RCGCSSI_R |= ssi_pins_data[ssi_index].ssi_clock_enable_bit;
    
    AFSEL(ssi_index) |= 1 << ssi_pins_data[ssi_index].clk_pin | 
                        1 << ssi_pins_data[ssi_index].rx_pin | 
                        1 << ssi_pins_data[ssi_index].tx_pin;
    
    DEN(ssi_index)   |= 1 << ssi_pins_data[ssi_index].clk_pin | 
                        1 << ssi_pins_data[ssi_index].rx_pin | 
                        1 << ssi_pins_data[ssi_index].tx_pin;

    PCTL(ssi_index) &= ~(0xF << ssi_pins_data[ssi_index].clk_pin * 4) &
                       ~(0xF << ssi_pins_data[ssi_index].fss_pin * 4) &     
                       ~(0xF << ssi_pins_data[ssi_index].rx_pin * 4)  & 
                       ~(0xF << ssi_pins_data[ssi_index].tx_pin * 4);

    
    PCTL(ssi_index) |= ssi_pins_data[ssi_index].pmc_setting << ssi_pins_data[ssi_index].clk_pin * 4 |
                       ssi_pins_data[ssi_index].pmc_setting << ssi_pins_data[ssi_index].rx_pin * 4  | 
                       ssi_pins_data[ssi_index].pmc_setting << ssi_pins_data[ssi_index].tx_pin * 4;
    
    if (config_fss_pin)
    {
        AFSEL(ssi_index) |= 1 << ssi_pins_data[ssi_index].fss_pin;
        DEN(ssi_index) |= 1 << ssi_pins_data[ssi_index].fss_pin;
        PCTL(ssi_index) |= ssi_pins_data[ssi_index].pmc_setting << ssi_pins_data[ssi_index].fss_pin * 4;
    }
    else
    {
        AFSEL(ssi_index) &= ~(1 << ssi_pins_data[ssi_index].fss_pin);
    }
          
    // Disable SSI
    SSICR1(ssi_index) &= ~SSI_CR1_SSE;
    
    
    // SCR = 0; SPH = 0; SPO = 0; FRF = 0 (Freescale SPI); DSS = 7 (8 bits) 
    SSICR0(ssi_index) = SSI_CR0_DSS_8;
    SSICC(ssi_index) = SSI_CC_CS_SYSPLL;
    SSICPSR(ssi_index) = 80;
    
    // Enable SSI in master mode
    SSICR1(ssi_index) = SSI_CR1_SSE;// | SSI_CR1_LBM;
}
Beispiel #7
0
void
mpq_set_z (mpq_ptr dest, mpz_srcptr src)
{
  mp_size_t num_size;
  mp_size_t abs_num_size;
  mp_ptr dp;

  num_size = SIZ (src);
  abs_num_size = ABS (num_size);
  dp = MPZ_NEWALLOC (NUM(dest), abs_num_size);
  SIZ(NUM(dest)) = num_size;
  MPN_COPY (dp, PTR(src), abs_num_size);

  PTR(DEN(dest))[0] = 1;
  SIZ(DEN(dest)) = 1;
}
Beispiel #8
0
void
mpq_init (mpq_t x)
{
  ALLOC(NUM(x)) = 1;
  PTR(NUM(x)) = __GMP_ALLOCATE_FUNC_LIMBS (1);
  SIZ(NUM(x)) = 0;
  ALLOC(DEN(x)) = 1;
  PTR(DEN(x)) = __GMP_ALLOCATE_FUNC_LIMBS (1);
  PTR(DEN(x))[0] = 1;
  SIZ(DEN(x)) = 1;

#ifdef __CHECKER__
  /* let the low limb look initialized, for the benefit of mpz_get_ui etc */
  PTR(NUM(x))[0] = 0;
#endif
}
Beispiel #9
0
void
mpq_init (MP_RAT *x)
{
  ALLOC(NUM(x)) = 1;
  PTR(NUM(x)) = (mp_ptr) (*__gmp_allocate_func) (BYTES_PER_MP_LIMB);
  SIZ(NUM(x)) = 0;
  ALLOC(DEN(x)) = 1;
  PTR(DEN(x)) = (mp_ptr) (*__gmp_allocate_func) (BYTES_PER_MP_LIMB);
  PTR(DEN(x))[0] = 1;
  SIZ(DEN(x)) = 1;

#ifdef __CHECKER__
  /* let the low limb look initialized, for the benefit of mpz_get_ui etc */
  PTR(NUM(x))[0] = 0;
#endif
}
Beispiel #10
0
void bs1770_add_sample(bs1770_t *bs1770, double fs, int channels,
    bs1770_sample_t sample)
{
  biquad_t *pre=&bs1770->pre;
  biquad_t *rlb=&bs1770->rlb;
  double wssqs=0.0;
  double *g=BS1770_G;
  int offs, size, i;
  int get_tmp;
  double den_tmp;

  if (bs1770->fs!=fs)
    bs1770_set_fs(bs1770, fs, channels);

  offs=bs1770->ring.offs;
  size=bs1770->ring.size;

  for (i=0;i<MIN(channels,BS1770_MAX_CHANNELS);++i) {
    double *buf=bs1770->ring.buf[i];
    double x=GETX(buf,offs,0)=DEN(sample[i]);

    if (1<size) {
      double y=GETY(buf,offs,0)=DEN(pre->b0*x
        +pre->b1*GETX(buf,offs,-1)+pre->b2*GETX(buf,offs,-2)
        -pre->a1*GETY(buf,offs,-1)-pre->a2*GETY(buf,offs,-2))
        ;
      double z=GETZ(buf,offs,0)=DEN(rlb->b0*y
        +rlb->b1*GETY(buf,offs,-1)+rlb->b2*GETY(buf,offs,-2)
        -rlb->a1*GETZ(buf,offs,-1)-rlb->a2*GETZ(buf,offs,-2))
        ;
      wssqs+=(*g++)*z*z;
      ++buf;
    }
  }

  if (NULL!=bs1770->lufs)
    bs1770_aggr_add_sqs(bs1770->lufs,fs,wssqs);

  if (NULL!=bs1770->lra)
    bs1770_aggr_add_sqs(bs1770->lra,fs,wssqs);

  if (size<2)
    ++bs1770->ring.size;

  if (++bs1770->ring.offs==BS1770_BUF_SIZE)
    bs1770->ring.offs=0;
}
Beispiel #11
0
void
mpq_set (mpq_ptr dest, mpq_srcptr src)
{
  mp_size_t num_size, den_size;
  mp_size_t abs_num_size;
  mp_ptr dp;

  num_size = SIZ(NUM(src));
  SIZ(NUM(dest)) = num_size;
  abs_num_size = ABS (num_size);
  dp = MPZ_NEWALLOC (NUM(dest), abs_num_size);
  MPN_COPY (dp, PTR(NUM(src)), abs_num_size);

  den_size = SIZ(DEN(src));
  SIZ(DEN(dest)) = den_size;
  dp = MPZ_NEWALLOC (DEN(dest), den_size);
  MPN_COPY (dp, PTR(DEN(src)), den_size);
}
Beispiel #12
0
void
mpq_abs (mpq_ptr dst, mpq_srcptr src)
{
  mp_size_t  num_abs_size = ABSIZ(NUM(src));

  if (dst != src)
    {
      mp_size_t  den_size = SIZ(DEN(src));
      mp_ptr dp;

      dp = MPZ_NEWALLOC (NUM(dst), num_abs_size);
      MPN_COPY (dp, PTR(NUM(src)), num_abs_size);

      dp = MPZ_NEWALLOC (DEN(dst), den_size);
      SIZ(DEN(dst)) = den_size;
      MPN_COPY (dp, PTR(DEN(src)), den_size);
    }

  SIZ(NUM(dst)) = num_abs_size;
}
Beispiel #13
0
size_t
mpq_inp_str (mpq_ptr q, FILE *fp, int base)
{
  size_t  nread;
  int     c;

  if (fp == NULL)
    fp = stdin;

  SIZ(DEN(q)) = 1;
  PTR(DEN(q))[0] = 1;

  nread = mpz_inp_str (mpq_numref(q), fp, base);
  if (nread == 0)
    return 0;

  c = getc (fp);
  nread++;

  if (c == '/')
    {
      c = getc (fp);
      nread++;

      nread = mpz_inp_str_nowhite (mpq_denref(q), fp, base, c, nread);
      if (nread == 0)
	{
	  SIZ(NUM(q)) = 0;
	  SIZ(DEN(q)) = 1;
	  PTR(DEN(q))[0] = 1;
	}
    }
  else
    {
      ungetc (c, fp);
      nread--;
    }

  return nread;
}
Beispiel #14
0
void
mpq_inv (mpq_ptr dest, mpq_srcptr src)
{
  mp_size_t num_size = SIZ(NUM(src));
  mp_size_t den_size = SIZ(DEN(src));

  if (num_size < 0)
    {
      num_size = -num_size;
      den_size = -den_size;
    }
  else if (UNLIKELY (num_size == 0))
    DIVIDE_BY_ZERO;

  SIZ(DEN(dest)) = num_size;
  SIZ(NUM(dest)) = den_size;

  /* If dest == src we may just swap the numerator and denominator;
     we ensured that the new denominator is positive.  */

  if (dest == src)
    {
      MP_PTR_SWAP (PTR(NUM(dest)), PTR(DEN(dest)));
      MP_SIZE_T_SWAP (ALLOC(NUM(dest)), ALLOC(DEN(dest)));
    }
  else
    {
      mp_ptr dp;

      den_size = ABS (den_size);
      dp = MPZ_NEWALLOC (NUM(dest), den_size);
      MPN_COPY (dp, PTR(DEN(src)), den_size);

      dp = MPZ_NEWALLOC (DEN(dest), num_size);
      MPN_COPY (dp, PTR(NUM(src)), num_size);
    }
}
Beispiel #15
0
void
mpq_set_f (mpq_ptr q, mpf_srcptr f)
{
  mp_size_t  fexp = EXP(f);
  mp_ptr     fptr = PTR(f);
  mp_size_t  fsize = SIZ(f);
  mp_size_t  abs_fsize = ABS(fsize);
  mp_limb_t  flow;

  if (fsize == 0)
    {
      /* set q=0 */
      SIZ(NUM(q)) = 0;
      SIZ(DEN(q)) = 1;
      PTR(DEN(q))[0] = 1;
      return;
    }

  /* strip low zero limbs from f */
  flow = *fptr;
  MPN_STRIP_LOW_ZEROS_NOT_ZERO (fptr, abs_fsize, flow);

  if (fexp >= abs_fsize)
    {
      /* radix point is to the right of the limbs, no denominator */
      mp_ptr  num_ptr;

      num_ptr = MPZ_NEWALLOC (mpq_numref (q), fexp);
      MPN_ZERO (num_ptr, fexp - abs_fsize);
      MPN_COPY (num_ptr + fexp - abs_fsize, fptr, abs_fsize);

      SIZ(NUM(q)) = fsize >= 0 ? fexp : -fexp;
      SIZ(DEN(q)) = 1;
      PTR(DEN(q))[0] = 1;
    }
  else
    {
      /* radix point is within or to the left of the limbs, use denominator */
      mp_ptr     num_ptr, den_ptr;
      mp_size_t  den_size;

      den_size = abs_fsize - fexp;
      num_ptr = MPZ_NEWALLOC (mpq_numref (q), abs_fsize);
      den_ptr = MPZ_NEWALLOC (mpq_denref (q), den_size+1);

      if (flow & 1)
        {
          /* no powers of two to strip from numerator */

          MPN_COPY (num_ptr, fptr, abs_fsize);
          MPN_ZERO (den_ptr, den_size);
          den_ptr[den_size] = 1;
        }
      else
        {
          /* right shift numerator, adjust denominator accordingly */
          int  shift;

          den_size--;
          count_trailing_zeros (shift, flow);

          mpn_rshift (num_ptr, fptr, abs_fsize, shift);
          abs_fsize -= (num_ptr[abs_fsize-1] == 0);

          MPN_ZERO (den_ptr, den_size);
          den_ptr[den_size] = GMP_LIMB_HIGHBIT >> (shift-1);
        }

      SIZ(NUM(q)) = fsize >= 0 ? abs_fsize : -abs_fsize;
      SIZ(DEN(q)) = den_size + 1;
    }
}
Beispiel #16
0
int
_mpq_cmp_ui (mpq_srcptr op1, unsigned long int num2, unsigned long int den2)
{
  mp_size_t num1_size = SIZ(NUM(op1));
  mp_size_t den1_size = SIZ(DEN(op1));
  mp_size_t tmp1_size, tmp2_size;
  mp_ptr tmp1_ptr, tmp2_ptr;
  mp_limb_t cy_limb;
  int cc;
  TMP_DECL;

#if GMP_NAIL_BITS != 0
  if ((num2 | den2) > GMP_NUMB_MAX)
    {
      mpq_t op2;
      mpq_init (op2);
      mpz_set_ui (mpq_numref (op2), num2);
      mpz_set_ui (mpq_denref (op2), den2);
      cc = mpq_cmp (op1, op2);
      mpq_clear (op2);
      return cc;
    }
#endif

  /* need canonical sign to get right result */
  ASSERT (den1_size > 0);

  if (UNLIKELY (den2 == 0))
    DIVIDE_BY_ZERO;

  if (num2 == 0)
    return num1_size;
  if (num1_size <= 0)
    return -1;

  /* NUM1 x DEN2 is either TMP1_SIZE limbs or TMP1_SIZE-1 limbs.
     Same for NUM1 x DEN1 with respect to TMP2_SIZE.  */
  if (num1_size > den1_size + 1)
    /* NUM1 x DEN2 is surely larger in magnitude than NUM2 x DEN1.  */
    return num1_size;
  if (den1_size > num1_size + 1)
    /* NUM1 x DEN2 is surely smaller in magnitude than NUM2 x DEN1.  */
    return -num1_size;

  TMP_MARK;
  TMP_ALLOC_LIMBS_2 (tmp1_ptr, num1_size + 1, tmp2_ptr, den1_size + 1);

  cy_limb = mpn_mul_1 (tmp1_ptr, PTR(NUM(op1)), num1_size,
                       (mp_limb_t) den2);
  tmp1_ptr[num1_size] = cy_limb;
  tmp1_size = num1_size + (cy_limb != 0);

  cy_limb = mpn_mul_1 (tmp2_ptr, PTR(DEN(op1)), den1_size,
                       (mp_limb_t) num2);
  tmp2_ptr[den1_size] = cy_limb;
  tmp2_size = den1_size + (cy_limb != 0);

  cc = tmp1_size - tmp2_size != 0
    ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size);
  TMP_FREE;
  return cc;
}
Beispiel #17
0
double
mpq_get_d (mpq_srcptr src)
{
  double res;
  mp_srcptr np, dp;
  mp_ptr remp, tp;
  mp_size_t nsize = SIZ(NUM(src));
  mp_size_t dsize = SIZ(DEN(src));
  mp_size_t qsize, prospective_qsize, zeros, chop, tsize;
  mp_size_t sign_quotient = nsize;
  long exp;
#define N_QLIMBS (1 + (sizeof (double) + GMP_LIMB_BYTES-1) / GMP_LIMB_BYTES)
  mp_limb_t qarr[N_QLIMBS + 1];
  mp_ptr qp = qarr;
  TMP_DECL;

  ASSERT (dsize > 0);    /* canonical src */

  /* mpn_get_d below requires a non-zero operand */
  if (UNLIKELY (nsize == 0))
    return 0.0;

  TMP_MARK;
  nsize = ABS (nsize);
  dsize = ABS (dsize);
  np = PTR(NUM(src));
  dp = PTR(DEN(src));

  prospective_qsize = nsize - dsize + 1;   /* from using given n,d */
  qsize = N_QLIMBS + 1;                    /* desired qsize */

  zeros = qsize - prospective_qsize;       /* padding n to get qsize */
  exp = (long) -zeros * GMP_NUMB_BITS;     /* relative to low of qp */

  chop = MAX (-zeros, 0);                  /* negative zeros means shorten n */
  np += chop;
  nsize -= chop;
  zeros += chop;                           /* now zeros >= 0 */

  tsize = nsize + zeros;                   /* size for possible copy of n */

  if (WANT_TMP_DEBUG)
    {
      /* separate blocks, for malloc debugging */
      remp = TMP_ALLOC_LIMBS (dsize);
      tp = (zeros > 0 ? TMP_ALLOC_LIMBS (tsize) : NULL);
    }
  else
    {
      /* one block with conditionalized size, for efficiency */
      remp = TMP_ALLOC_LIMBS (dsize + (zeros > 0 ? tsize : 0));
      tp = remp + dsize;
    }

  /* zero extend n into temporary space, if necessary */
  if (zeros > 0)
    {
      MPN_ZERO (tp, zeros);
      MPN_COPY (tp+zeros, np, nsize);
      np = tp;
      nsize = tsize;
    }

  ASSERT (qsize == nsize - dsize + 1);
  mpn_tdiv_qr (qp, remp, (mp_size_t) 0, np, nsize, dp, dsize);

  /* strip possible zero high limb */
  qsize -= (qp[qsize-1] == 0);

  res = mpn_get_d (qp, qsize, sign_quotient, exp);
  TMP_FREE;
  return res;
}
Beispiel #18
0
int
mpq_cmp (const MP_RAT *op1, const MP_RAT *op2)
{
  mp_size_t num1_size = SIZ(NUM(op1));
  mp_size_t den1_size = SIZ(DEN(op1));
  mp_size_t num2_size = SIZ(NUM(op2));
  mp_size_t den2_size = SIZ(DEN(op2));
  mp_size_t tmp1_size, tmp2_size;
  mp_ptr tmp1_ptr, tmp2_ptr;
  mp_size_t num1_sign;
  int cc;
  TMP_DECL;

  /* need canonical signs to get right result */
  ASSERT (den1_size > 0);
  ASSERT (den2_size > 0);

  if (num1_size == 0)
    return -num2_size;
  if (num2_size == 0)
    return num1_size;
  if ((num1_size ^ num2_size) < 0) /* I.e. are the signs different? */
    return num1_size;

  num1_sign = num1_size;
  num1_size = ABS (num1_size);
  num2_size = ABS (num2_size);

  tmp1_size = num1_size + den2_size;
  tmp2_size = num2_size + den1_size;

  /* 1. Check to see if we can tell which operand is larger by just looking at
     the number of limbs.  */

  /* NUM1 x DEN2 is either TMP1_SIZE limbs or TMP1_SIZE-1 limbs.
     Same for NUM1 x DEN1 with respect to TMP2_SIZE.  */
  if (tmp1_size > tmp2_size + 1)
    /* NUM1 x DEN2 is surely larger in magnitude than NUM2 x DEN1.  */
    return num1_sign;
  if (tmp2_size > tmp1_size + 1)
    /* NUM1 x DEN2 is surely smaller in magnitude than NUM2 x DEN1.  */
    return -num1_sign;

  /* 2. Same, but compare the number of significant bits.  */
  {
    int cnt1, cnt2;
    mp_bitcnt_t bits1, bits2;

    count_leading_zeros (cnt1, PTR(NUM(op1))[num1_size - 1]);
    count_leading_zeros (cnt2, PTR(DEN(op2))[den2_size - 1]);
    bits1 = tmp1_size * GMP_NUMB_BITS - cnt1 - cnt2 + 2 * GMP_NAIL_BITS;

    count_leading_zeros (cnt1, PTR(NUM(op2))[num2_size - 1]);
    count_leading_zeros (cnt2, PTR(DEN(op1))[den1_size - 1]);
    bits2 = tmp2_size * GMP_NUMB_BITS - cnt1 - cnt2 + 2 * GMP_NAIL_BITS;

    if (bits1 > bits2 + 1)
      return num1_sign;
    if (bits2 > bits1 + 1)
      return -num1_sign;
  }

  /* 3. Finally, cross multiply and compare.  */

  TMP_MARK;
  TMP_ALLOC_LIMBS_2 (tmp1_ptr,tmp1_size, tmp2_ptr,tmp2_size);

  if (num1_size >= den2_size)
    tmp1_size -= 0 == mpn_mul (tmp1_ptr,
			       PTR(NUM(op1)), num1_size,
			       PTR(DEN(op2)), den2_size);
  else
    tmp1_size -= 0 == mpn_mul (tmp1_ptr,
			       PTR(DEN(op2)), den2_size,
			       PTR(NUM(op1)), num1_size);

   if (num2_size >= den1_size)
     tmp2_size -= 0 == mpn_mul (tmp2_ptr,
				PTR(NUM(op2)), num2_size,
				PTR(DEN(op1)), den1_size);
   else
     tmp2_size -= 0 == mpn_mul (tmp2_ptr,
				PTR(DEN(op1)), den1_size,
				PTR(NUM(op2)), num2_size);


  cc = tmp1_size - tmp2_size != 0
    ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size);
  TMP_FREE;
  return num1_sign < 0 ? -cc : cc;
}
Beispiel #19
0
  choke me
#endif

void
mpq_set_d (mpq_ptr dest, double d)
{
  int negative;
  mp_exp_t exp;
  mp_limb_t tp[LIMBS_PER_DOUBLE];
  mp_ptr np, dp;
  mp_size_t nn, dn;
  int c;

  DOUBLE_NAN_INF_ACTION (d,
                         __gmp_invalid_operation (),
                         __gmp_invalid_operation ());

  negative = d < 0;
  d = ABS (d);

  exp = __gmp_extract_double (tp, d);

  /* There are two main version of the conversion.  The `then' arm handles
     numbers with a fractional part, while the `else' arm handles integers.  */
#if LIMBS_PER_DOUBLE == 4
  if (exp <= 1 || (exp == 2 && (tp[0] | tp[1]) != 0))
#endif
#if LIMBS_PER_DOUBLE == 3
  if (exp <= 1 || (exp == 2 && tp[0] != 0))
#endif
#if LIMBS_PER_DOUBLE == 2
  if (exp <= 1)
#endif
    {
      if (d == 0.0)
	{
	  SIZ(NUM(dest)) = 0;
	  SIZ(DEN(dest)) = 1;
	  PTR(DEN(dest))[0] = 1;
	  return;
	}

#if LIMBS_PER_DOUBLE == 4
      np = MPZ_NEWALLOC (NUM(dest), 4);
      if ((tp[0] | tp[1] | tp[2]) == 0)
	np[0] = tp[3], nn = 1;
      else if ((tp[0] | tp[1]) == 0)
	np[1] = tp[3], np[0] = tp[2], nn = 2;
      else if (tp[0] == 0)
	np[2] = tp[3], np[1] = tp[2], np[0] = tp[1], nn = 3;
      else
	np[3] = tp[3], np[2] = tp[2], np[1] = tp[1], np[0] = tp[0], nn = 4;
#endif
#if LIMBS_PER_DOUBLE == 3
      np = MPZ_NEWALLOC (NUM(dest), 3);
      if ((tp[0] | tp[1]) == 0)
	np[0] = tp[2], nn = 1;
      else if (tp[0] == 0)
	np[1] = tp[2], np[0] = tp[1], nn = 2;
      else
	np[2] = tp[2], np[1] = tp[1], np[0] = tp[0], nn = 3;
#endif
#if LIMBS_PER_DOUBLE == 2
      np = MPZ_NEWALLOC (NUM(dest), 2);
      if (tp[0] == 0)
	np[0] = tp[1], nn = 1;
      else
	np[1] = tp[1], np[0] = tp[0], nn = 2;
#endif
      dn = nn + 1 - exp;
      ASSERT (dn > 0); /* -exp >= -1; nn >= 1*/
      dp = MPZ_NEWALLOC (DEN(dest), dn);
      MPN_ZERO (dp, dn - 1);
      dp[dn - 1] = 1;
      count_trailing_zeros (c, np[0] | dp[0]);
      if (c != 0)
	{
	  mpn_rshift (np, np, nn, c);
	  nn -= np[nn - 1] == 0;
	  --dn;
	  dp[dn - 1] = CNST_LIMB(1) << (GMP_LIMB_BITS - c);
	}
      SIZ(DEN(dest)) = dn;
    }
  else
    {
      nn = exp;
      np = MPZ_NEWALLOC (NUM(dest), nn);
      switch (nn)
        {
	default:
	  MPN_ZERO (np, nn - LIMBS_PER_DOUBLE);
	  np += nn - LIMBS_PER_DOUBLE;
	  /* fall through */
#if LIMBS_PER_DOUBLE == 2
	case 2:
	  np[1] = tp[1], np[0] = tp[0];
	  break;
#endif
#if LIMBS_PER_DOUBLE == 3
	case 3:
	  np[2] = tp[2], np[1] = tp[1], np[0] = tp[0];
	  break;
	case 2:
	  np[1] = tp[2], np[0] = tp[1];
	  break;
#endif
#if LIMBS_PER_DOUBLE == 4
	case 4:
	  np[3] = tp[3], np[2] = tp[2], np[1] = tp[1], np[0] = tp[0];
	  break;
	case 3:
	  np[2] = tp[3], np[1] = tp[2], np[0] = tp[1];
	  break;
	case 2:
	  np[1] = tp[3], np[0] = tp[2];
	  break;
#endif
	}
      *PTR(DEN(dest)) = 1;
      SIZ(DEN(dest)) = 1;
    }
  SIZ(NUM(dest)) = negative ? -nn : nn;
}