示例#1
0
void
mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace)
{
    if( size & 1 ) {
	/* The size is odd, and the code below doesn't handle that.
	 * Multiply the least significant (size - 1) limbs with a recursive
	 * call, and handle the most significant limb of S1 and S2
	 * separately.
	 * A slightly faster way to do this would be to make the Karatsuba
	 * code below behave as if the size were even, and let it check for
	 * odd size in the end.  I.e., in essence move this code to the end.
	 * Doing so would save us a recursive call, and potentially make the
	 * stack grow a lot less.
	 */
	mpi_size_t esize = size - 1;	   /* even size */
	mpi_limb_t cy_limb;

	MPN_SQR_N_RECURSE( prodp, up, esize, tspace );
	cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] );
	prodp[esize + esize] = cy_limb;
	cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] );

	prodp[esize + size] = cy_limb;
    }
    else {
	mpi_size_t hsize = size >> 1;
	mpi_limb_t cy;

	/* Product H.	   ________________  ________________
	 *		  |_____U1 x U1____||____U0 x U0_____|
	 * Put result in upper part of PROD and pass low part of TSPACE
	 * as new TSPACE.
	 */
	MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace);

	/* Product M.	   ________________
	 *		  |_(U1-U0)(U0-U1)_|
	 */
	if( mpihelp_cmp( up + hsize, up, hsize) >= 0 )
	    mpihelp_sub_n( prodp, up + hsize, up, hsize);
	else
	    mpihelp_sub_n (prodp, up, up + hsize, hsize);

	/* Read temporary operands from low part of PROD.
	 * Put result in low part of TSPACE using upper part of TSPACE
	 * as new TSPACE.  */
	MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size);

	/* Add/copy product H  */
	MPN_COPY(prodp + hsize, prodp + size, hsize);
	cy = mpihelp_add_n(prodp + size, prodp + size,
			   prodp + size + hsize, hsize);

	/* Add product M (if NEGFLG M is a negative number).  */
	cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size);

	/* Product L.	   ________________  ________________
	 *		  |________________||____U0 x U0_____|
	 * Read temporary operands from low part of PROD.
	 * Put result in low part of TSPACE using upper part of TSPACE
	 * as new TSPACE.  */
	MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size);

	/* Add/copy Product L (twice).	*/
	cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size);
	if( cy )
	    mpihelp_add_1(prodp + hsize + size, prodp + hsize + size,
							    hsize, cy);

	MPN_COPY(prodp, tspace, hsize);
	cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
	if( cy )
	    mpihelp_add_1 (prodp + size, prodp + size, size, 1);
    }
}
int mpi_add(MPI w, MPI u, MPI 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;
		if (RESIZE_IF_NEEDED(w, wsize) < 0)
			return -ENOMEM;
		
		up = v->d;
		vp = u->d;
	} else {
		usize = u->nlimbs;
		usign = u->sign;
		vsize = v->nlimbs;
		vsign = v->sign;
		wsize = usize + 1;
		if (RESIZE_IF_NEEDED(w, wsize) < 0)
			return -ENOMEM;
		
		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) {
			mpihelp_sub(wp, up, usize, vp, vsize);
			wsize = usize;
			MPN_NORMALIZE(wp, wsize);
			wsign = usign;
		} else if (mpihelp_cmp(up, vp, usize) < 0) {
			mpihelp_sub_n(wp, vp, up, usize);
			wsize = usize;
			MPN_NORMALIZE(wp, wsize);
			if (!usign)
				wsign = 1;
		} else {
			mpihelp_sub_n(wp, up, vp, usize);
			wsize = usize;
			MPN_NORMALIZE(wp, wsize);
			if (usign)
				wsign = 1;
		}
	} else {		
		mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
		wp[usize] = cy;
		wsize = usize + cy;
		if (usign)
			wsign = 1;
	}

	w->nlimbs = wsize;
	w->sign = wsign;
	return 0;
}
示例#3
0
static void
mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp,
			mpi_size_t size, mpi_ptr_t tspace )
{
    if( size & 1 ) {
      /* The size is odd, and the code below doesn't handle that.
       * Multiply the least significant (size - 1) limbs with a recursive
       * call, and handle the most significant limb of S1 and S2
       * separately.
       * A slightly faster way to do this would be to make the Karatsuba
       * code below behave as if the size were even, and let it check for
       * odd size in the end.  I.e., in essence move this code to the end.
       * Doing so would save us a recursive call, and potentially make the
       * stack grow a lot less.
       */
      mpi_size_t esize = size - 1;	 /* even size */
      mpi_limb_t cy_limb;

      MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace );
      cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] );
      prodp[esize + esize] = cy_limb;
      cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] );
      prodp[esize + size] = cy_limb;
    }
    else {
	/* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm.
	 *
	 * Split U in two pieces, U1 and U0, such that
	 * U = U0 + U1*(B**n),
	 * and V in V1 and V0, such that
	 * V = V0 + V1*(B**n).
	 *
	 * UV is then computed recursively using the identity
	 *
	 *	  2n   n	  n			n
	 * UV = (B  + B )U V  +  B (U -U )(V -V )  +  (B + 1)U V
	 *		  1 1	     1	0   0  1	      0 0
	 *
	 * Where B = 2**BITS_PER_MP_LIMB.
	 */
	mpi_size_t hsize = size >> 1;
	mpi_limb_t cy;
	int negflg;

	/* Product H.	   ________________  ________________
	 *		  |_____U1 x V1____||____U0 x V0_____|
	 * Put result in upper part of PROD and pass low part of TSPACE
	 * as new TSPACE.
	 */
	MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace);

	/* Product M.	   ________________
	 *		  |_(U1-U0)(V0-V1)_|
	 */
	if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) {
	    mpihelp_sub_n(prodp, up + hsize, up, hsize);
	    negflg = 0;
	}
	else {
	    mpihelp_sub_n(prodp, up, up + hsize, hsize);
	    negflg = 1;
	}
	if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) {
	    mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize);
	    negflg ^= 1;
	}
	else {
	    mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize);
	    /* No change of NEGFLG.  */
	}
	/* Read temporary operands from low part of PROD.
	 * Put result in low part of TSPACE using upper part of TSPACE
	 * as new TSPACE.
	 */
	MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size);

	/* Add/copy product H. */
	MPN_COPY (prodp + hsize, prodp + size, hsize);
	cy = mpihelp_add_n( prodp + size, prodp + size,
			    prodp + size + hsize, hsize);

	/* Add product M (if NEGFLG M is a negative number) */
	if(negflg)
	    cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size);
	else
	    cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size);

	/* Product L.	   ________________  ________________
	 *		  |________________||____U0 x V0_____|
	 * Read temporary operands from low part of PROD.
	 * Put result in low part of TSPACE using upper part of TSPACE
	 * as new TSPACE.
	 */
	MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size);

	/* Add/copy Product L (twice) */

	cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size);
	if( cy )
	  mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy);

	MPN_COPY(prodp, tspace, hsize);
	cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize);
	if( cy )
	    mpihelp_add_1(prodp + size, prodp + size, size, 1);
    }
}
示例#4
0
文件: mpi-add.c 项目: BridgeNY/purdue
void
mpi_add(MPI w, MPI u, MPI v)
{
    mpi_ptr_t wp, up, vp;
    mpi_size_t usize, vsize, wsize;
    int usign, vsign, wsign;

    if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
	usize = v->nlimbs;
	usign = v->sign;
	vsize = u->nlimbs;
	vsign = u->sign;
	wsize = usize + 1;
	RESIZE_IF_NEEDED(w, wsize);
	/* These must be after realloc (u or v may be the same as w).  */
	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);
	/* These must be after realloc (u or v may be the same as w).  */
	up    = u->d;
	vp    = v->d;
    }
    wp = w->d;
    wsign = 0;

    if( !vsize ) {  /* simple */
	MPN_COPY(wp, up, usize );
	wsize = usize;
	wsign = usign;
    }
    else if( usign != vsign ) { /* different sign */
	/* This test is right since USIZE >= VSIZE */
	if( usize != vsize ) {
	    mpihelp_sub(wp, up, usize, vp, vsize);
	    wsize = usize;
	    MPN_NORMALIZE(wp, wsize);
	    wsign = usign;
	}
	else if( mpihelp_cmp(up, vp, usize) < 0 ) {
	    mpihelp_sub_n(wp, vp, up, usize);
	    wsize = usize;
	    MPN_NORMALIZE(wp, wsize);
	    if( !usign )
		wsign = 1;
	}
	else {
	    mpihelp_sub_n(wp, up, vp, usize);
	    wsize = usize;
	    MPN_NORMALIZE(wp, wsize);
	    if( usign )
		wsign = 1;
	}
    }
    else { /* U and V have same sign. Add them. */
	mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
	wp[usize] = cy;
	wsize = usize + cy;
	if( usign )
	    wsign = 1;
    }

    w->nlimbs = wsize;
    w->sign = wsign;
}