Blame mpn/generic/sec_div.c

Packit 5c3484
/* mpn_sec_div_qr, mpn_sec_div_r -- Compute Q = floor(U / V), U = U mod V.
Packit 5c3484
   Side-channel silent under the assumption that the used instructions are
Packit 5c3484
   side-channel silent.
Packit 5c3484
Packit 5c3484
   Contributed to the GNU project by Torbjörn Granlund.
Packit 5c3484
Packit 5c3484
Copyright 2011-2014 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
#include "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
#include "longlong.h"
Packit 5c3484
Packit 5c3484
#if OPERATION_sec_div_qr
Packit 5c3484
#define FNAME mpn_sec_div_qr
Packit 5c3484
#define FNAME_itch mpn_sec_div_qr_itch
Packit 5c3484
#define Q(q) q,
Packit 5c3484
#define RETTYPE mp_limb_t
Packit 5c3484
#endif
Packit 5c3484
#if OPERATION_sec_div_r
Packit 5c3484
#define FNAME mpn_sec_div_r
Packit 5c3484
#define FNAME_itch mpn_sec_div_r_itch
Packit 5c3484
#define Q(q)
Packit 5c3484
#define RETTYPE void
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
mp_size_t
Packit 5c3484
FNAME_itch (mp_size_t nn, mp_size_t dn)
Packit 5c3484
{
Packit 5c3484
#if OPERATION_sec_div_qr
Packit 5c3484
/* Needs (nn + dn + 1) + mpn_sec_pi1_div_qr's needs of (2nn' - dn + 1) for a
Packit 5c3484
   total of 3nn + 4 limbs at tp.  Note that mpn_sec_pi1_div_qr's nn is one
Packit 5c3484
   greater than ours, therefore +4 and not just +2.  */
Packit 5c3484
  return 3 * nn + 4;
Packit 5c3484
#endif
Packit 5c3484
#if OPERATION_sec_div_r
Packit 5c3484
/* Needs (nn + dn + 1) + mpn_sec_pi1_div_r's needs of (dn + 1) for a total of
Packit 5c3484
   nn + 2dn + 2 limbs at tp.  */
Packit 5c3484
  return nn + 2 * dn + 2;
Packit 5c3484
#endif
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
RETTYPE
Packit 5c3484
FNAME (Q(mp_ptr qp)
Packit 5c3484
       mp_ptr np, mp_size_t nn,
Packit 5c3484
       mp_srcptr dp, mp_size_t dn,
Packit 5c3484
       mp_ptr tp)
Packit 5c3484
{
Packit 5c3484
  mp_limb_t d1, d0;
Packit 5c3484
  unsigned int cnt;
Packit 5c3484
  gmp_pi1_t dinv;
Packit 5c3484
  mp_limb_t inv32;
Packit 5c3484
Packit 5c3484
  ASSERT (dn >= 1);
Packit 5c3484
  ASSERT (nn >= dn);
Packit 5c3484
  ASSERT (dp[dn - 1] != 0);
Packit 5c3484
Packit 5c3484
  d1 = dp[dn - 1];
Packit 5c3484
  count_leading_zeros (cnt, d1);
Packit 5c3484
Packit 5c3484
  if (cnt != 0)
Packit 5c3484
    {
Packit 5c3484
      mp_limb_t qh, cy;
Packit 5c3484
      mp_ptr np2, dp2;
Packit 5c3484
      dp2 = tp;					/* dn limbs */
Packit 5c3484
      mpn_lshift (dp2, dp, dn, cnt);
Packit 5c3484
Packit 5c3484
      np2 = tp + dn;				/* (nn + 1) limbs */
Packit 5c3484
      cy = mpn_lshift (np2, np, nn, cnt);
Packit 5c3484
      np2[nn++] = cy;
Packit 5c3484
Packit 5c3484
      d0 = dp2[dn - 1];
Packit 5c3484
      d0 += (~d0 != 0);
Packit 5c3484
      invert_limb (inv32, d0);
Packit 5c3484
Packit 5c3484
      /* We add nn + dn to tp here, not nn + 1 + dn, as expected.  This is
Packit 5c3484
	 since nn here will have been incremented.  */
Packit 5c3484
#if OPERATION_sec_div_qr
Packit 5c3484
      qh = mpn_sec_pi1_div_qr (np2 + dn, np2, nn, dp2, dn, inv32, tp + nn + dn);
Packit 5c3484
      ASSERT (qh == 0);		/* FIXME: this indicates inefficiency! */
Packit 5c3484
      MPN_COPY (qp, np2 + dn, nn - dn - 1);
Packit 5c3484
      qh = np2[nn - 1];
Packit 5c3484
#else
Packit 5c3484
      mpn_sec_pi1_div_r (np2, nn, dp2, dn, inv32, tp + nn + dn);
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
      mpn_rshift (np, np2, dn, cnt);
Packit 5c3484
Packit 5c3484
#if OPERATION_sec_div_qr
Packit 5c3484
      return qh;
Packit 5c3484
#endif
Packit 5c3484
    }
Packit 5c3484
  else
Packit 5c3484
    {
Packit 5c3484
      /* FIXME: Consider copying np => np2 here, adding a 0-limb at the top.
Packit 5c3484
	 That would simplify the underlying pi1 function, since then it could
Packit 5c3484
	 assume nn > dn.  */
Packit 5c3484
      d0 = dp[dn - 1];
Packit 5c3484
      d0 += (~d0 != 0);
Packit 5c3484
      invert_limb (inv32, d0);
Packit 5c3484
Packit 5c3484
#if OPERATION_sec_div_qr
Packit 5c3484
      return mpn_sec_pi1_div_qr (qp, np, nn, dp, dn, inv32, tp);
Packit 5c3484
#else
Packit 5c3484
      mpn_sec_pi1_div_r (np, nn, dp, dn, inv32, tp);
Packit 5c3484
#endif
Packit 5c3484
    }
Packit 5c3484
}