Torbjorn Granlund wrote:
...
> > * We have some hardwired W_TYPE_SIZE settings for the code interfacing
> > to longlong.h. It is now 64 bits. It will break on systems where
> > uintmax_t is not a 64-bit type. Please see the beginning of
> > factor.c.
>
> I wonder how many types of systems would be affected.
>
> It is not used currently anywhere in coreutils? Perhaps coreutils could
uintmax_t is used throughout coreutils, but nowhere (that comes to mind)
does it fail when UINTMAX_MAX happens to be different than 2^64-1.
What I was wondering is how many systems have a uintmax_t that is
only 32 bits wide. Now that I reread, I suppose this code would be
ok (albeit slower) with uintmax_t wider than 64.
> use autoconf for checking this? (If we're really crazy, we could speed
> the factor program by an additional 20% by using blocked input with
> e.g. fread.)
>
> Please take a look at the generated code for factor_using_division,
> towards the end where 8 imulq should be found (on amd64). The code uses
> mov, imul, cmp, jbe for testing the divisibility of a prime; the branch
> is taken when the prime divides the number being factored, thus highly
> non-taken. (I suppose we could do a better job at describing the maths,
> with some references. This particular trick is from "Division by
> invariant integers using multiplication".)
Any place you can add a reference would be most welcome.
Here's one where I'd appreciate a reference in a comment:
#define MAGIC64 ((uint64_t) 0x0202021202030213ULL)
#define MAGIC63 ((uint64_t) 0x0402483012450293ULL)
#define MAGIC65 ((uint64_t) 0x218a019866014613ULL)
#define MAGIC11 0x23b
/* Returns the square root if the input is a square, otherwise 0. */
static uintmax_t
is_square (uintmax_t x)
{
/* Uses the tests suggested by Cohen. Excludes 99% of squares before
computing the square root. */
if (((MAGIC64 >> (x & 63)) & 1)
&& ((MAGIC63 >> (x % 63)) & 1)
/* Both 0 and 64 are squares mod (65) */
&& ((MAGIC65 >> ((x % 65) & 63)) & 1)
&& ((MAGIC11 >> (x % 11) & 1)))
{
uintmax_t r = isqrt (x);
if (r*r == x)
return r;
}
return 0;
}