divexact_1 and bdiv_q_1

bodrato at mail.dm.unipi.it bodrato at mail.dm.unipi.it
Thu Jan 20 10:45:13 CET 2011


Ciao Niels,

On Wed, January 19, 2011 7:34 pm, Niels Möller wrote:
> If I remember correctly, it should work like this. Inputs are U (n
> limbs) and d (single limb, and odd!). Then we should get back Q (n

Both divexact_1 and bdiv_q_1 accept an even divisor. They remove any even
factor, then implement (or call) a pi1_bdiv_q_1 routine.

> limbs), defined by Q = U d^{-1} (mod B^n) and and r (single limb) such
> that
>
>   U = Q * d - B^n r

A comment from mpn/generic/dive1_c reads:
   mpn_divexact_1c could be created, accepting and returning c.  This would
   let a long calculation be done piece by piece.  Currently there's no
   particular need for that, and not returning c means that a final umul can
   be skipped.
As far as I can understand, returning the correct r needs some more work,
but is never used...

> (This is a bit different from the interface of general bdiv, where an
> n/1 division would produce a quotient of n-1 limbs and a remainder

Well... bdiv_q does not return any reminder, and I do not expect any
returned by bdiv_q_1.

> So it seems that at least r == 0 if and only if d divides U, which makes

This sounds reasonable... but there currently are two implementations.
The C version in mpn/generic/bdiv_q_1.c containing:

mp_limb_t
mpn_bdiv_q_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t d)
{
...
  return mpn_pi1_bdiv_q_1 (rp, up, n, d, di, shift);
}

mp_limb_t
mpn_pi1_bdiv_q_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t d,
		  mp_limb_t di, int shift)
{
...
      c = 0;
...
      for (i = 1; i < n; i++) /* modifies c, but is skipped if n==1 */
...
   return c;
}

I mean, if size (n) is one, the returned value is always zero, regardless
of divisibility.


The asm version in mpn/x86_64/bdiv_q_1.asm contains:
...
	C rdi	rp end
...
	mov	%rax, (%rdi)
	pop	%rbx
	ret

The returned value is the most significant limb of the result, right?


My mpn/x86/bdiv_q_1.asm implementation should return the most significant
limb too. This can be useful for the typical
  cy = bdiv_q_1 ( ..., size, ...);
  size -= (cy == 0);
This could also be extended to bdiv_q, so that one could write
  cy = bdiv_q ( ..., num_size, ..., den_size, ...);
  quotient_size = num_size - den_size  + (cy != 0);
if we desire a coherent interface.

Regards,
Marco

-- 
http://bodrato.it/papers/



More information about the gmp-devel mailing list