#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
void
_gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
{
mpi_ptr_t wp, up;
mpi_size_t usize, wsize;
int usign, wsign;
usize = u->nlimbs;
usign = u->sign;
wsign = 0;
wsize = usize + 1;
if( w->alloced < wsize )
mpi_resize(w, wsize);
up = u->d;
wp = w->d;
if( !usize ) {
wp[0] = v;
wsize = v? 1:0;
}
else if( !usign ) {
mpi_limb_t cy;
cy = _gcry_mpih_add_1(wp, up, usize, v);
wp[usize] = cy;
wsize = usize + cy;
}
else {
if( usize == 1 && up[0] < v ) {
wp[0] = v - up[0];
wsize = 1;
}
else {
_gcry_mpih_sub_1(wp, up, usize, v);
wsize = usize - (wp[usize-1]==0);
wsign = 1;
}
}
w->nlimbs = wsize;
w->sign = wsign;
}
void
_gcry_mpi_add(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
{
mpi_ptr_t wp, up, vp;
mpi_size_t usize, vsize, wsize;
int usign, vsign, wsign;
if( u->nlimbs < v->nlimbs ) {
usize = v->nlimbs;
usign = v->sign;
vsize = u->nlimbs;
vsign = u->sign;
wsize = usize + 1;
RESIZE_IF_NEEDED(w, wsize);
up = v->d;
vp = u->d;
}
else {
usize = u->nlimbs;
usign = u->sign;
vsize = v->nlimbs;
vsign = v->sign;
wsize = usize + 1;
RESIZE_IF_NEEDED(w, wsize);
up = u->d;
vp = v->d;
}
wp = w->d;
wsign = 0;
if( !vsize ) {
MPN_COPY(wp, up, usize );
wsize = usize;
wsign = usign;
}
else if( usign != vsign ) {
if( usize != vsize ) {
_gcry_mpih_sub(wp, up, usize, vp, vsize);
wsize = usize;
MPN_NORMALIZE(wp, wsize);
wsign = usign;
}
else if( _gcry_mpih_cmp(up, vp, usize) < 0 ) {
_gcry_mpih_sub_n(wp, vp, up, usize);
wsize = usize;
MPN_NORMALIZE(wp, wsize);
if( !usign )
wsign = 1;
}
else {
_gcry_mpih_sub_n(wp, up, vp, usize);
wsize = usize;
MPN_NORMALIZE(wp, wsize);
if( usign )
wsign = 1;
}
}
else {
mpi_limb_t cy = _gcry_mpih_add(wp, up, usize, vp, vsize);
wp[usize] = cy;
wsize = usize + cy;
if( usign )
wsign = 1;
}
w->nlimbs = wsize;
w->sign = wsign;
}
void
_gcry_mpi_sub_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
{
mpi_ptr_t wp, up;
mpi_size_t usize, wsize;
int usign, wsign;
usize = u->nlimbs;
usign = u->sign;
wsign = 0;
wsize = usize + 1;
if( w->alloced < wsize )
mpi_resize(w, wsize);
up = u->d;
wp = w->d;
if( !usize ) {
wp[0] = v;
wsize = v? 1:0;
wsign = 1;
}
else if( usign ) {
mpi_limb_t cy;
cy = _gcry_mpih_add_1(wp, up, usize, v);
wp[usize] = cy;
wsize = usize + cy;
}
else {
if( usize == 1 && up[0] < v ) {
wp[0] = v - up[0];
wsize = 1;
wsign = 1;
}
else {
_gcry_mpih_sub_1(wp, up, usize, v);
wsize = usize - (wp[usize-1]==0);
}
}
w->nlimbs = wsize;
w->sign = wsign;
}
void
_gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
{
gcry_mpi_t vv = mpi_copy (v);
vv->sign = ! vv->sign;
mpi_add (w, u, vv);
mpi_free (vv);
}
void
_gcry_mpi_addm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
{
mpi_add (w, u, v);
mpi_mod (w, w, m);
}
void
_gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
{
mpi_sub (w, u, v);
mpi_mod (w, w, m);
}