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

📄 bigfunc.c

📁 随机数算法
💻 C
📖 第 1 页 / 共 2 页
字号:
      b = (2^.5 + 1)/(2^.5 - 1)*/  sum.degree = 0;  if( !get_space( &sum))   {    printf("no space left, calc_ln_coef\n");    return 0;  }/*  compute bconst first  */  int_to_float( 2, &r);  square_root( &r, &root2);  one(&temp);  add( &root2, &temp, &r);  subtract( &root2, &temp, &bconst);  divide( &r, &bconst, &bconst);/*  now compute r and r^2 */  square_root( &root2, &r);  subtract( &r, &temp, &root2);  add( &r, &temp, &r);  divide( &root2, &r, &r);  multiply( &r, &r, &rsqrd);  for( i=1; i<=maxdegree; i += 2)  {    int_to_float( i, &temp);    divide( &r, &temp, &temp);    multi_dup( cheb[i], &term);    for( j=1; j<=i; j+=2)    {      iptr = Address( term) + j;      multiply( &temp, iptr, iptr);    }    if( !multi_add( term, sum, &sum)) break;    free_space( &term);    multiply( &rsqrd, &r, &r);  /*  r^2k+1  */  }  if( i< maxdegree) free_space( &term);  else i = maxdegree;/*  multiply all coefficients by 4/ln(2)  */  one( &temp);  temp.expnt += 2;  divide( &temp, &ln2, &temp);  for( j=1; j<=i; j+=2)  {    iptr = Address(sum) + j;    multiply( &temp, iptr, iptr);  }  multi_dup( sum, log2coef);  free_space(&sum);  return(i);}/*  evaluate simple polynomial.	Input:  MULTIPOLY coefficients, pointer to x, pointer to y	Output:  y = F(x)	y can equal x*/void polyeval( MULTIPOLY coef, FLOAT *x, FLOAT *y){	INDEX 	i;	FLOAT	sum, *cof;		null( &sum);	for( i=coef.degree; i>0; i--)	{		cof = Address( coef) + i;		add( cof, &sum, &sum);		multiply( x, &sum, &sum);	}	cof = Address( coef);	add( cof, &sum, y);}/*  compute 2^x for x in the range -1 ... 1.	Most inputs will be in range +/- .5 ... 1 but this routine could handle	unnormalized inputs.	Enter with pointer to input and storage for output	Returns y = 2^x ( works in place, both pointers can be the same)*/void twoexp( FLOAT *x, FLOAT *y){	polyeval( twoxcoef, x, y);}/*  compute cos( x) for x in range +/- PI/2	As above, works in place.	This is a *core* routine, no range checking!*/void corecos(FLOAT *x, FLOAT *y){	FLOAT	x2;		divide( x, &P2, &x2);	multiply( &x2, &x2, &x2);	polyeval( coscoef, &x2, y);}/*  convert a float to a long.  Overflow is max	possible result.*/int	float_to_int( FLOAT *f){	FLOAT	dummy, intprt;	int		value;		if( f->expnt < 1) return 0;	if( f->expnt > 31)	{		if( f->mntsa.e[MS_MNTSA] & SIGN_BIT)			return SIGN_BIT;		return ~SIGN_BIT;	}	split( f, &intprt, &dummy);	if( intprt.mntsa.e[MS_MNTSA] & SIGN_BIT)	{		negate( &intprt);		value = -(intprt.mntsa.e[MS_MNTSA] >> ( 31 - intprt.expnt));	}	else	value = intprt.mntsa.e[MS_MNTSA] >> ( 31 - intprt.expnt);	return value;}/*  compute log base 2 of FLOAT.    range of input for valid result is 1 <= t <= 2.    See page 52 of "Chebyshev Methods in Numerical Approximation",     M. A. Snyder, Prentice-Hall, 1966 for details    input pointer can equal output pointer and it will still work.*/void logbase2( FLOAT *t, FLOAT *y){  INDEX  i;  FLOAT  x, temp, root2, sum, xsqrd, *cofptr;/*  construct x = (t - 2^.5)/(t + 2^.5) * bconst  */  int_to_float( 2, &temp);  square_root( &temp, &root2);  subtract( t, &root2, &temp);  add( t, &root2, &x);  divide( &temp, &x, &x);  multiply( &x, &bconst, &x);  null( &sum);/*  use x^2 to do polynomial expansion since only odd powers used  */  multiply( &x, &x, &xsqrd);  for( i=log2coef.degree; i>1; i -= 2)  {    cofptr = Address( log2coef) + i;    add( cofptr, &sum, &sum);    multiply( &xsqrd, &sum, &sum);  }/*  add on last term to mak it all odd powers */  cofptr = Address( log2coef) + 1;  add( cofptr, &sum, &sum);  multiply( &x, &sum, &sum);/*  add final 0.5  */  one( &temp);  temp.expnt--;  add( &temp, &sum, y);}/*  compute e^x for any x.  |x| > 2^32/ln(2) will overflow	and return max possible value and 0.	Otherwise returns y = exp(x) and 1.	works in place.*/int big_exp( FLOAT *x, FLOAT *y){	FLOAT	z, xp;	long		xpnt;	INDEX	i;	/*  convert to base 2  */	divide( x, &ln2, &z);	/*  check range is possible to do  */	if (z.expnt > 32)	{		if( x->mntsa.e[MS_MNTSA] & SIGN_BIT)			null(y);		else		{			OPLOOP(i) y->mntsa.e[MS_MNTSA] = ~0;			y->mntsa.e[MS_MNTSA] >>= 1;			y->expnt = ~0 >> 1;		}		return 0;	}	/*  we can perform operation, send z mods 2 to core */	split(&z, &xp, &z);	xpnt = float_to_int( &xp);	twoexp( &z, y);	/*  next add xpnt to exponent of y  */	y->expnt +=  xpnt;	return 1;}/*  split a FLOAT into its integer and fractional parts  */void split( FLOAT *x, FLOAT *intprt, FLOAT *frac){	FLOAT	fracpart;	INDEX	i, signflag;	ELEMENT	mask, xpchk;/*  if number < 1, return just a fraction  */		if( x->expnt <= 0)	{		null( intprt);		copy( x, frac);		return;	}/*  zero out 31 bits of ms word, then one block at a time */	copy( x, &fracpart);	signflag = 0;	if( fracpart.mntsa.e[MS_MNTSA] & SIGN_BIT)	{		negate( &fracpart);		signflag = 1;	}	i = MS_MNTSA;	xpchk = fracpart.expnt;	if( xpchk > 31)	{		fracpart.mntsa.e[i] = 0;		i--;		xpchk -= 31;	}	while( (xpchk > 32) && ( i>0 ))	{		fracpart.mntsa.e[i] = 0;		i--;		xpchk -= 32;	}/*  next zero out the remaining integer bits in a left over word  */	if( i != MS_MNTSA) mask = ~0UL >> xpchk;	else 	mask = ( ~0UL >> (xpchk+1));	fracpart.mntsa.e[i] &= mask;	if( signflag) negate( &fracpart);	normal( &fracpart);	subtract( x, &fracpart, intprt);	copy( &fracpart, frac);}/*  compute cosine(x) for any x.	x values larger than PI*2^200 will be in gross error, so watch out!	works in place, returns y = cos(x)*/void cosine( FLOAT *x, FLOAT *y){	FLOAT	z, PI, dummy, PI3;	int		cmpr;	/*  create 2*PI  */	copy( &P2, &PI);	PI.expnt += 2;/*  check range of input and force modulo 2PI operation  */	cmpr = compare( x, &PI);	if( cmpr > 0 )	{		divide( x, &PI, &z);		split( &z, &dummy, &z);		multiply( &PI, &z, &z);	}	else copy( x, &z);	if( z.mntsa.e[MS_MNTSA] & SIGN_BIT) negate( &z);/*  z is now in range 0...2PI.  Now convert to range of core cos */	cmpr = compare( &z, &P2);	if( cmpr <= 0)	{		corecos( &z, y);		return;	}	PI.expnt--;	add( &PI, &P2, &PI3);	// 3 PI/2	cmpr = compare( &z, &PI3);	if( cmpr > 0)	{		PI.expnt++;		subtract( &PI, &z, &z);	// 2PI - x		corecos( &z, y);		return;	}	subtract( &PI, &z, &z);	// PI - x	corecos( &z, y);	negate( y);}/*  compute sine(x) for any x.	same as cosine, jus move arguments around.	works in place, 	returns y = sin(x)*/void sine( FLOAT *x, FLOAT *y){	FLOAT	z, PI, dummy;	int		cmpr, signflag;	/*  create 2*PI and reduce x modulo 2PI signed  */	copy( &P2, &PI);	PI.expnt += 2;	cmpr = compare( x, &PI);	if( cmpr > 0)	{		divide( x, &PI, &z);		split( &z, &dummy, &z);		multiply( &PI, &z, &z);	}	else copy( x, &z);	if( z.mntsa.e[MS_MNTSA] & SIGN_BIT)	{		negate( &z);		signflag = 1;	}	else signflag = 0;/*  z is no in range 0... 2*PI.	if bigger than PI, flip sign of result and fold back to 0..PI,	then subtract PI/2 to put into corecos range.*/	PI.expnt--;	cmpr = compare( &z, &PI);	if( cmpr > 0)	{		signflag ^= 1;		subtract( &z, &PI, &z);	}	subtract( &z, &P2, &z);	corecos( &z, y);	if( signflag) negate(y);}/*  compute natural logarithm of big FLOAT value.    values <= 0 return 0 and null result.    Returns value to desired location.  Pointers can    be the same and this will work.  Returns 1 if    calculation valid.*/int big_ln( FLOAT *x, FLOAT *y){  FLOAT  t, kn;  ELEMENT n;/*  check if input negative or zero  */  if( (x->mntsa.e[MS_MNTSA] & SIGN_BIT) || iszero(x))   {    null( y);    return 0;  }/*  split out fractional part in range 1..2 and feed to    approximation routine  */  n = x->expnt - 1;  copy( x, &t);  t.expnt = 1;   logbase2( &t, &t);  int_to_float( n, &kn);  add( &kn, &t, &t);  multiply( &ln2, &t, y);}

⌨️ 快捷键说明

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