Blame mpn/generic/add_err3_n.c

Packit 5c3484
/* mpn_add_err3_n -- add_n with three error terms
Packit 5c3484
Packit 5c3484
   Contributed by David Harvey.
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'LL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
Packit 5c3484
Packit 5c3484
Copyright 2011 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
Packit 5c3484
/*
Packit 5c3484
  Computes:
Packit 5c3484
Packit 5c3484
  (1) {rp,n} := {up,n} + {vp,n} (just like mpn_add_n) with incoming carry cy,
Packit 5c3484
  return value is carry out.
Packit 5c3484
Packit 5c3484
  (2) Let c[i+1] = carry from i-th limb addition (c[0] = cy).
Packit 5c3484
  Computes c[1]*yp1[n-1] + ... + c[n]*yp1[0],
Packit 5c3484
           c[1]*yp2[n-1] + ... + c[n]*yp2[0],
Packit 5c3484
           c[1]*yp3[n-1] + ... + c[n]*yp3[0],
Packit 5c3484
  stores two-limb results at {ep,2}, {ep+2,2} and {ep+4,2} respectively.
Packit 5c3484
Packit 5c3484
  Requires n >= 1.
Packit 5c3484
Packit 5c3484
  None of the outputs may overlap each other or any of the inputs, except
Packit 5c3484
  that {rp,n} may be equal to {up,n} or {vp,n}.
Packit 5c3484
*/
Packit 5c3484
mp_limb_t
Packit 5c3484
mpn_add_err3_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp,
Packit 5c3484
                mp_ptr ep, mp_srcptr yp1, mp_srcptr yp2, mp_srcptr yp3,
Packit 5c3484
                mp_size_t n, mp_limb_t cy)
Packit 5c3484
{
Packit 5c3484
  mp_limb_t el1, eh1, el2, eh2, el3, eh3, ul, vl, yl1, yl2, yl3, zl1, zl2, zl3, rl, sl, cy1, cy2;
Packit 5c3484
Packit 5c3484
  ASSERT (n >= 1);
Packit 5c3484
  ASSERT (MPN_SAME_OR_SEPARATE_P (rp, up, n));
Packit 5c3484
  ASSERT (MPN_SAME_OR_SEPARATE_P (rp, vp, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (rp, n, yp1, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (rp, n, yp2, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (rp, n, yp3, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (ep, 6, up, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (ep, 6, vp, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (ep, 6, yp1, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (ep, 6, yp2, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (ep, 6, yp3, n));
Packit 5c3484
  ASSERT (! MPN_OVERLAP_P (ep, 6, rp, n));
Packit 5c3484
Packit 5c3484
  yp1 += n - 1;
Packit 5c3484
  yp2 += n - 1;
Packit 5c3484
  yp3 += n - 1;
Packit 5c3484
  el1 = eh1 = 0;
Packit 5c3484
  el2 = eh2 = 0;
Packit 5c3484
  el3 = eh3 = 0;
Packit 5c3484
Packit 5c3484
  do
Packit 5c3484
    {
Packit 5c3484
      yl1 = *yp1--;
Packit 5c3484
      yl2 = *yp2--;
Packit 5c3484
      yl3 = *yp3--;
Packit 5c3484
      ul = *up++;
Packit 5c3484
      vl = *vp++;
Packit 5c3484
Packit 5c3484
      /* ordinary add_n */
Packit 5c3484
      ADDC_LIMB (cy1, sl, ul, vl);
Packit 5c3484
      ADDC_LIMB (cy2, rl, sl, cy);
Packit 5c3484
      cy = cy1 | cy2;
Packit 5c3484
      *rp++ = rl;
Packit 5c3484
Packit 5c3484
      /* update (eh1:el1) */
Packit 5c3484
      zl1 = (-cy) & yl1;
Packit 5c3484
      el1 += zl1;
Packit 5c3484
      eh1 += el1 < zl1;
Packit 5c3484
Packit 5c3484
      /* update (eh2:el2) */
Packit 5c3484
      zl2 = (-cy) & yl2;
Packit 5c3484
      el2 += zl2;
Packit 5c3484
      eh2 += el2 < zl2;
Packit 5c3484
Packit 5c3484
      /* update (eh3:el3) */
Packit 5c3484
      zl3 = (-cy) & yl3;
Packit 5c3484
      el3 += zl3;
Packit 5c3484
      eh3 += el3 < zl3;
Packit 5c3484
    }
Packit 5c3484
  while (--n);
Packit 5c3484
Packit 5c3484
#if GMP_NAIL_BITS != 0
Packit 5c3484
  eh1 = (eh1 << GMP_NAIL_BITS) + (el1 >> GMP_NUMB_BITS);
Packit 5c3484
  el1 &= GMP_NUMB_MASK;
Packit 5c3484
  eh2 = (eh2 << GMP_NAIL_BITS) + (el2 >> GMP_NUMB_BITS);
Packit 5c3484
  el2 &= GMP_NUMB_MASK;
Packit 5c3484
  eh3 = (eh3 << GMP_NAIL_BITS) + (el3 >> GMP_NUMB_BITS);
Packit 5c3484
  el3 &= GMP_NUMB_MASK;
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
  ep[0] = el1;
Packit 5c3484
  ep[1] = eh1;
Packit 5c3484
  ep[2] = el2;
Packit 5c3484
  ep[3] = eh2;
Packit 5c3484
  ep[4] = el3;
Packit 5c3484
  ep[5] = eh3;
Packit 5c3484
Packit 5c3484
  return cy;
Packit 5c3484
}