Blame mpn/generic/trialdiv.c

Packit 5c3484
/* mpn_trialdiv -- find small factors of an mpn number using trial division.
Packit 5c3484
Packit 5c3484
   Contributed to the GNU project by Torbjorn Granlund.
Packit 5c3484
Packit 5c3484
   THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE.  IT IS ONLY
Packit 5c3484
   SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
Packit 5c3484
   GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
Packit 5c3484
Packit 5c3484
Copyright 2009, 2010, 2012, 2013 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library.
Packit 5c3484
Packit 5c3484
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
it under the terms of either:
Packit 5c3484
Packit 5c3484
  * the GNU Lesser General Public License as published by the Free
Packit 5c3484
    Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
    option) any later version.
Packit 5c3484
Packit 5c3484
or
Packit 5c3484
Packit 5c3484
  * the GNU General Public License as published by the Free Software
Packit 5c3484
    Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
    later version.
Packit 5c3484
Packit 5c3484
or both in parallel, as here.
Packit 5c3484
Packit 5c3484
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
for more details.
Packit 5c3484
Packit 5c3484
You should have received copies of the GNU General Public License and the
Packit 5c3484
GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
/*
Packit 5c3484
   This function finds the first (smallest) factor represented in
Packit 5c3484
   trialdivtab.h.  It does not stop the factoring effort just because it has
Packit 5c3484
   reached some sensible limit, such as the square root of the input number.
Packit 5c3484
Packit 5c3484
   The caller can limit the factoring effort by passing NPRIMES.  The function
Packit 5c3484
   will then divide until that limit, or perhaps a few primes more.  A position
Packit 5c3484
   which only mpn_trialdiv can make sense of is returned in the WHERE
Packit 5c3484
   parameter.  It can be used for restarting the factoring effort; the first
Packit 5c3484
   call should pass 0 here.
Packit 5c3484
Packit 5c3484
   Input:        1. A non-negative number T = {tp,tn}
Packit 5c3484
                 2. NPRIMES as described above,
Packit 5c3484
                 3. *WHERE as described above.
Packit 5c3484
   Output:       1. *WHERE updated as described above.
Packit 5c3484
                 2. Return value is non-zero if we found a factor, else zero
Packit 5c3484
                    To get the actual prime factor, compute the mod B inverse
Packit 5c3484
                    of the return value.
Packit 5c3484
*/
Packit 5c3484
Packit 5c3484
#include "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
Packit 5c3484
struct gmp_primes_dtab {
Packit 5c3484
  mp_limb_t binv;
Packit 5c3484
  mp_limb_t lim;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct gmp_primes_ptab {
Packit 5c3484
  mp_limb_t ppp;	/* primes, multiplied together */
Packit 5c3484
  mp_limb_t cps[7];	/* ppp values pre-computed for mpn_mod_1s_4p */
Packit 5c3484
  gmp_uint_least32_t idx:24;	/* index of  first primes in dtab */
Packit 5c3484
  gmp_uint_least32_t np :8;	/* number of primes related to this entry */
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
Packit 5c3484
static const struct gmp_primes_dtab gmp_primes_dtab[] =
Packit 5c3484
{
Packit 5c3484
#define WANT_dtab
Packit 5c3484
#define P(p,inv,lim) {inv,lim}
Packit 5c3484
#include "trialdivtab.h"
Packit 5c3484
#undef WANT_dtab
Packit 5c3484
#undef P
Packit 5c3484
  {0,0}
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
static const struct gmp_primes_ptab gmp_primes_ptab[] =
Packit 5c3484
{
Packit 5c3484
#define WANT_ptab
Packit 5c3484
#include "trialdivtab.h"
Packit 5c3484
#undef WANT_ptab
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
#define PTAB_LINES (sizeof (gmp_primes_ptab) / sizeof (gmp_primes_ptab[0]))
Packit 5c3484
Packit 5c3484
/* FIXME: We could optimize out one of the outer loop conditions if we
Packit 5c3484
   had a final ptab entry with a huge np field.  */
Packit 5c3484
mp_limb_t
Packit 5c3484
mpn_trialdiv (mp_srcptr tp, mp_size_t tn, mp_size_t nprimes, int *where)
Packit 5c3484
{
Packit 5c3484
  mp_limb_t ppp;
Packit 5c3484
  const mp_limb_t *cps;
Packit 5c3484
  const struct gmp_primes_dtab *dp;
Packit 5c3484
  long i, j, idx, np;
Packit 5c3484
  mp_limb_t r, q;
Packit 5c3484
Packit 5c3484
  ASSERT (tn >= 1);
Packit 5c3484
Packit 5c3484
  for (i = *where; i < PTAB_LINES; i++)
Packit 5c3484
    {
Packit 5c3484
      ppp = gmp_primes_ptab[i].ppp;
Packit 5c3484
      cps = gmp_primes_ptab[i].cps;
Packit 5c3484
Packit 5c3484
      r = mpn_mod_1s_4p (tp, tn, ppp << cps[1], cps);
Packit 5c3484
Packit 5c3484
      idx = gmp_primes_ptab[i].idx;
Packit 5c3484
      np = gmp_primes_ptab[i].np;
Packit 5c3484
Packit 5c3484
      /* Check divisibility by individual primes.  */
Packit 5c3484
      dp = &gmp_primes_dtab[idx] + np;
Packit 5c3484
      for (j = -np; j < 0; j++)
Packit 5c3484
	{
Packit 5c3484
	  q = r * dp[j].binv;
Packit 5c3484
	  if (q <= dp[j].lim)
Packit 5c3484
	    {
Packit 5c3484
	      *where = i;
Packit 5c3484
	      return dp[j].binv;
Packit 5c3484
	    }
Packit 5c3484
	}
Packit 5c3484
Packit 5c3484
      nprimes -= np;
Packit 5c3484
      if (nprimes <= 0)
Packit 5c3484
	return 0;
Packit 5c3484
    }
Packit 5c3484
  return 0;
Packit 5c3484
}