/* Copyright (c) 2009 Ian Piumarta
 * All rights reserved.
 * See the file COPYING for details.
 */

#include "_mpint.h"

/* r = r + ~a + 1 */

mp_digit_t mp_sub(mp_t *r, mp_t *a)
{
  if (mp_zerop(a)) return 0;
  mp_digit_t c= 1;
  size_t v= a->width, w= _mp_max(r->width, v), i= 0;
  _mp_grow(r, w);
  while (i < v) {
#  if defined(__MP_64__)
    mp_digit2_t s= (mp_digit2_t)_mp_digitAt(r, i) + (mp_digit2_t)~_mp_digitAt(a, i) + c;
    _mp_digitAtPut(r, i++, s);
    c= (s >> MP_BITS) /*& 1*/;
#  else
    mp_digit_t x=  _mp_digitAt(r, i);
    mp_digit_t y= ~_mp_digitAt(a, i);
    mp_digit_t s=  x + y + c;
    _mp_digitAtPut(r, i++, s);
    c= ((x & y) | ((x | y) & ~s)) >> (MP_BITS - 1);				assert(c == (((mp_digit2_t)x + (mp_digit2_t)y + (mp_digit2_t)c) >> MP_BITS));
#  endif
  }
  while (i < w) {
#  if defined(__MP_64__)
    mp_digit2_t s= (mp_digit2_t)_mp_digitAt(r, i) + ~(mp_digit_t)0 + c;
    _mp_digitAtPut(r, i++, s);
    c= (s >> MP_BITS) & 1;
#  else
    mp_digit_t x= _mp_digitAt(r, i);
    mp_digit_t s= x + ~(mp_digit_t)0 + c;
    _mp_digitAtPut(r, i++, s);
    c= ((x & ~(mp_digit_t)0) | ((x | ~(mp_digit_t)0) & ~s)) >> (MP_BITS - 1);	assert(c == (((mp_digit2_t)x + ~(mp_digit_t)0 + (mp_digit2_t)c) >> MP_BITS));
#  endif
  }
  mp_normalise(r);
  return c;
}

