⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bn_mul.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* crypto/bn/bn_mul.c *//* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. *  * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to.  The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code.  The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). *  * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *    "This product includes cryptographic software written by *     Eric Young (eay@cryptsoft.com)" *    The word 'cryptographic' can be left out if the rouines from the library *    being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from  *    the apps directory (application code) you must include an acknowledgement: *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" *  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *  * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed.  i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */#ifndef BN_DEBUG# undef NDEBUG /* avoid conflicting definitions */# define NDEBUG#endif#include <stdio.h>#include <assert.h>#include "cryptlib.h"#include "bn_lcl.h"#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)/* Here follows specialised variants of bn_add_words() and   bn_sub_words().  They have the property performing operations on   arrays of different sizes.  The sizes of those arrays is expressed through   cl, which is the common length ( basicall, min(len(a),len(b)) ), and dl,   which is the delta between the two lengths, calculated as len(a)-len(b).   All lengths are the number of BN_ULONGs...  For the operations that require   a result array as parameter, it must have the length cl+abs(dl).   These functions should probably end up in bn_asm.c as soon as there are   assembler counterparts for the systems that use assembler files.  */BN_ULONG bn_sub_part_words(BN_ULONG *r,	const BN_ULONG *a, const BN_ULONG *b,	int cl, int dl)	{	BN_ULONG c, t;	assert(cl >= 0);	c = bn_sub_words(r, a, b, cl);	if (dl == 0)		return c;	r += cl;	a += cl;	b += cl;	if (dl < 0)		{#ifdef BN_COUNT		fprintf(stderr, "  bn_sub_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c);#endif		for (;;)			{			t = b[0];			r[0] = (0-t-c)&BN_MASK2;			if (t != 0) c=1;			if (++dl >= 0) break;			t = b[1];			r[1] = (0-t-c)&BN_MASK2;			if (t != 0) c=1;			if (++dl >= 0) break;			t = b[2];			r[2] = (0-t-c)&BN_MASK2;			if (t != 0) c=1;			if (++dl >= 0) break;			t = b[3];			r[3] = (0-t-c)&BN_MASK2;			if (t != 0) c=1;			if (++dl >= 0) break;			b += 4;			r += 4;			}		}	else		{		int save_dl = dl;#ifdef BN_COUNT		fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, c = %d)\n", cl, dl, c);#endif		while(c)			{			t = a[0];			r[0] = (t-c)&BN_MASK2;			if (t != 0) c=0;			if (--dl <= 0) break;			t = a[1];			r[1] = (t-c)&BN_MASK2;			if (t != 0) c=0;			if (--dl <= 0) break;			t = a[2];			r[2] = (t-c)&BN_MASK2;			if (t != 0) c=0;			if (--dl <= 0) break;			t = a[3];			r[3] = (t-c)&BN_MASK2;			if (t != 0) c=0;			if (--dl <= 0) break;			save_dl = dl;			a += 4;			r += 4;			}		if (dl > 0)			{#ifdef BN_COUNT			fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);#endif			if (save_dl > dl)				{				switch (save_dl - dl)					{				case 1:					r[1] = a[1];					if (--dl <= 0) break;				case 2:					r[2] = a[2];					if (--dl <= 0) break;				case 3:					r[3] = a[3];					if (--dl <= 0) break;					}				a += 4;				r += 4;				}			}		if (dl > 0)			{#ifdef BN_COUNT			fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, copy)\n", cl, dl);#endif			for(;;)				{				r[0] = a[0];				if (--dl <= 0) break;				r[1] = a[1];				if (--dl <= 0) break;				r[2] = a[2];				if (--dl <= 0) break;				r[3] = a[3];				if (--dl <= 0) break;				a += 4;				r += 4;				}			}		}	return c;	}#endifBN_ULONG bn_add_part_words(BN_ULONG *r,	const BN_ULONG *a, const BN_ULONG *b,	int cl, int dl)	{	BN_ULONG c, l, t;	assert(cl >= 0);	c = bn_add_words(r, a, b, cl);	if (dl == 0)		return c;	r += cl;	a += cl;	b += cl;	if (dl < 0)		{		int save_dl = dl;#ifdef BN_COUNT		fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c);#endif		while (c)			{			l=(c+b[0])&BN_MASK2;			c=(l < c);			r[0]=l;			if (++dl >= 0) break;			l=(c+b[1])&BN_MASK2;			c=(l < c);			r[1]=l;			if (++dl >= 0) break;			l=(c+b[2])&BN_MASK2;			c=(l < c);			r[2]=l;			if (++dl >= 0) break;			l=(c+b[3])&BN_MASK2;			c=(l < c);			r[3]=l;			if (++dl >= 0) break;			save_dl = dl;			b+=4;			r+=4;			}		if (dl < 0)			{#ifdef BN_COUNT			fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, c == 0)\n", cl, dl);#endif			if (save_dl < dl)				{				switch (dl - save_dl)					{				case 1:					r[1] = b[1];					if (++dl >= 0) break;				case 2:					r[2] = b[2];					if (++dl >= 0) break;				case 3:					r[3] = b[3];					if (++dl >= 0) break;					}				b += 4;				r += 4;				}			}		if (dl < 0)			{#ifdef BN_COUNT			fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, copy)\n", cl, dl);#endif			for(;;)				{				r[0] = b[0];				if (++dl >= 0) break;				r[1] = b[1];				if (++dl >= 0) break;				r[2] = b[2];				if (++dl >= 0) break;				r[3] = b[3];				if (++dl >= 0) break;				b += 4;				r += 4;				}			}		}	else		{		int save_dl = dl;#ifdef BN_COUNT		fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0)\n", cl, dl);#endif		while (c)			{			t=(a[0]+c)&BN_MASK2;			c=(t < c);			r[0]=t;			if (--dl <= 0) break;			t=(a[1]+c)&BN_MASK2;			c=(t < c);			r[1]=t;			if (--dl <= 0) break;			t=(a[2]+c)&BN_MASK2;			c=(t < c);			r[2]=t;			if (--dl <= 0) break;			t=(a[3]+c)&BN_MASK2;			c=(t < c);			r[3]=t;			if (--dl <= 0) break;			save_dl = dl;			a+=4;			r+=4;			}#ifdef BN_COUNT		fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);#endif		if (dl > 0)			{			if (save_dl > dl)				{				switch (save_dl - dl)					{				case 1:					r[1] = a[1];					if (--dl <= 0) break;				case 2:					r[2] = a[2];					if (--dl <= 0) break;				case 3:					r[3] = a[3];					if (--dl <= 0) break;					}				a += 4;				r += 4;				}			}		if (dl > 0)			{#ifdef BN_COUNT			fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0, copy)\n", cl, dl);#endif			for(;;)				{				r[0] = a[0];				if (--dl <= 0) break;				r[1] = a[1];				if (--dl <= 0) break;				r[2] = a[2];				if (--dl <= 0) break;				r[3] = a[3];				if (--dl <= 0) break;				a += 4;				r += 4;				}			}		}	return c;	}#ifdef BN_RECURSION/* Karatsuba recursive multiplication algorithm * (cf. Knuth, The Art of Computer Programming, Vol. 2) *//* r is 2*n2 words in size, * a and b are both n2 words in size. * n2 must be a power of 2. * We multiply and return the result. * t must be 2*n2 words in size * We calculate * a[0]*b[0] * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) * a[1]*b[1] */void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,	int dna, int dnb, BN_ULONG *t)	{	int n=n2/2,c1,c2;	int tna=n+dna, tnb=n+dnb;	unsigned int neg,zero;	BN_ULONG ln,lo,*p;# ifdef BN_COUNT	fprintf(stderr," bn_mul_recursive %d * %d\n",n2,n2);# endif# ifdef BN_MUL_COMBA#  if 0	if (n2 == 4)		{		bn_mul_comba4(r,a,b);		return;		}#  endif	/* Only call bn_mul_comba 8 if n2 == 8 and the	 * two arrays are complete [steve]	 */	if (n2 == 8 && dna == 0 && dnb == 0)		{		bn_mul_comba8(r,a,b);		return; 		}# endif /* BN_MUL_COMBA */	/* Else do normal multiply */	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)		{		bn_mul_normal(r,a,n2+dna,b,n2+dnb);		if ((dna + dnb) < 0)			memset(&r[2*n2 + dna + dnb], 0,				sizeof(BN_ULONG) * -(dna + dnb));		return;		}	/* r=(a[0]-a[1])*(b[1]-b[0]) */	c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna);	c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n);	zero=neg=0;	switch (c1*3+c2)		{	case -4:		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */		break;	case -3:		zero=1;		break;	case -2:		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n); /* + */		neg=1;		break;	case -1:	case 0:	case 1:		zero=1;		break;	case 2:		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna); /* + */		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */		neg=1;		break;	case 3:		zero=1;		break;	case 4:		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna);		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n);		break;		}# ifdef BN_MUL_COMBA	if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take					       extra args to do this well */		{		if (!zero)			bn_mul_comba4(&(t[n2]),t,&(t[n]));		else			memset(&(t[n2]),0,8*sizeof(BN_ULONG));				bn_mul_comba4(r,a,b);		bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));		}	else if (n == 8 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could						    take extra args to do this						    well */		{		if (!zero)			bn_mul_comba8(&(t[n2]),t,&(t[n]));		else			memset(&(t[n2]),0,16*sizeof(BN_ULONG));				bn_mul_comba8(r,a,b);		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));		}	else# endif /* BN_MUL_COMBA */		{		p= &(t[n2*2]);		if (!zero)			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,0,0,p);		else			memset(&(t[n2]),0,n2*sizeof(BN_ULONG));		bn_mul_recursive(r,a,b,n,0,0,p);		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,dna,dnb,p);		}	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign	 * r[10] holds (a[0]*b[0])	 * r[32] holds (b[1]*b[1])	 */	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));	if (neg) /* if t[32] is negative */		{		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));		}	else		{		/* Might have a carry */		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));		}	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])	 * r[10] holds (a[0]*b[0])	 * r[32] holds (b[1]*b[1])	 * c1 holds the carry bits	 */	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));	if (c1)		{		p= &(r[n+n2]);		lo= *p;		ln=(lo+c1)&BN_MASK2;		*p=ln;		/* The overflow will stop before we over write		 * words we should not overwrite */		if (ln < (BN_ULONG)c1)			{			do	{				p++;				lo= *p;				ln=(lo+1)&BN_MASK2;				*p=ln;				} while (ln == 0);			}		}	}/* n+tn is the word length * t needs to be n*4 is size, as does r */void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,	     int tna, int tnb, BN_ULONG *t)	{	int i,j,n2=n*2;	int c1,c2,neg,zero;	BN_ULONG ln,lo,*p;# ifdef BN_COUNT	fprintf(stderr," bn_mul_part_recursive (%d+%d) * (%d+%d)\n",		tna, n, tnb, n);# endif	if (n < 8)		{		bn_mul_normal(r,a,n+tna,b,n+tnb);		return;		}	/* r=(a[0]-a[1])*(b[1]-b[0]) */	c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna);	c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n);	zero=neg=0;	switch (c1*3+c2)		{	case -4:		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */		break;	case -3:		zero=1;		/* break; */	case -2:		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n); /* + */		neg=1;		break;	case -1:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -