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

#include "_mpint.h"

/* r = r + a */

mp_t *mp_add(mp_t *r, mp_t *a)
{
  if (mp_zerop(a)) return r;
  if (mp_zerop(r)) return mp_copy(r, a);
  mp_digit_t c= 0;
  size_t v= a->width, w= _mp_max(r->width, v), i= 0;
  _mp_grow(r, w);
  assert(v == a->width && v > 0);
  assert(w == r->width && w >= v);
  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;
#  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 (c && i < w) {
    c += _mp_digitAt(r, i);
    _mp_digitAtPut(r, i++, c);
    c= !c;
  }
  if (c) mp_digitAtPut(r, w, 1);
  return r;
}

