Example #1
0
void	M_4x_cos(M_APM r, int places, M_APM x)
{
M_APM   tmp8, tmp9;

tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();

/* 
 *  if  |x| >= 1.0   use multiple angle identity 4 times
 *  if  |x|  < 1.0   use multiple angle identity 3 times
 */

if (x->m_apm_exponent > 0)
  {
   m_apm_multiply(tmp9, x, MM_5x_256R);        /* 1 / (4*4*4*4) */
   M_raw_cos(tmp8, (places + 8), tmp9);
   M_4x_do_it(tmp9, (places + 8), tmp8);
   M_4x_do_it(tmp8, (places + 6), tmp9);
   M_4x_do_it(tmp9, (places + 4), tmp8);
   M_4x_do_it(r, places, tmp9);
  }
else
  {
   m_apm_multiply(tmp9, x, MM_5x_64R);         /* 1 / (4*4*4) */
   M_raw_cos(tmp8, (places + 6), tmp9);
   M_4x_do_it(tmp9, (places + 4), tmp8);
   M_4x_do_it(tmp8, (places + 4), tmp9);
   M_4x_do_it(r, places, tmp8);
  }

M_restore_stack(2);
}
Example #2
0
/*
	calculate arctan (x) with the following series:

                               x^3     x^5     x^7     x^9
	arctan (x)  ==   x  -  ---  +  ---  -  ---  +  ---  ...
                                3       5       7       9

*/
void	M_arctan_near_0(M_APM rr, int places, M_APM aa)
{
M_APM   tmp0, tmpR, tmp2, tmpS, digit, term;
int	tolerance,  local_precision;
long    m1;

tmp0  = M_get_stack_var();
tmp2  = M_get_stack_var();
tmpR  = M_get_stack_var();
tmpS  = M_get_stack_var();
term  = M_get_stack_var();
digit = M_get_stack_var();

tolerance       = aa->m_apm_exponent - places - 4;
local_precision = places + 8 - aa->m_apm_exponent;

m_apm_copy(term, aa);
m_apm_copy(tmpS, aa);
m_apm_multiply(tmp0, aa, aa);
m_apm_round(tmp2, (local_precision + 8), tmp0);

m1 = 1;

while (TRUE)
  {
   m1 += 2;
   m_apm_set_long(digit, m1);
   m_apm_multiply(tmp0, term, tmp2);
   m_apm_round(term, local_precision, tmp0);
   m_apm_divide(tmp0, local_precision, term, digit);
   m_apm_subtract(tmpR, tmpS, tmp0);

   if ((tmp0->m_apm_exponent < tolerance) || (tmp0->m_apm_sign == 0))
     {
      m_apm_round(rr, places, tmpR);
      break;
     }

   m1 += 2;
   m_apm_set_long(digit, m1);
   m_apm_multiply(tmp0, term, tmp2);
   m_apm_round(term, local_precision, tmp0);
   m_apm_divide(tmp0, local_precision, term, digit);
   m_apm_add(tmpS, tmpR, tmp0);

   if ((tmp0->m_apm_exponent < tolerance) || (tmp0->m_apm_sign == 0))
     {
      m_apm_round(rr, places, tmpS);
      break;
     }
  }

M_restore_stack(6);                    /* restore the 6 locals we used here */
}
Example #3
0
/*
	calculate log (1 + x) with the following series:

              x
	y = -----      ( |y| < 1 )
	    x + 2


            [ 1 + y ]                 y^3     y^5     y^7
	log [-------]  =  2 * [ y  +  ---  +  ---  +  ---  ... ] 
            [ 1 - y ]                  3       5       7 

*/
void	M_log_near_1(M_APM rr, int places, M_APM xx)
{
M_APM   tmp0, tmp1, tmp2, tmpS, term;
int	tolerance, dplaces, local_precision;
long    m1;

tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
tmpS = M_get_stack_var();
term = M_get_stack_var();

tolerance = xx->m_apm_exponent - (places + 6);
dplaces   = (places + 12) - xx->m_apm_exponent;

m_apm_add(tmp0, xx, MM_Two);
m_apm_divide(tmpS, (dplaces + 6), xx, tmp0);

m_apm_copy(term, tmpS);
m_apm_multiply(tmp0, tmpS, tmpS);
m_apm_round(tmp2, (dplaces + 6), tmp0);

m1 = 3L;

while (TRUE)
  {
   m_apm_multiply(tmp0, term, tmp2);

   if ((tmp0->m_apm_exponent < tolerance) || (tmp0->m_apm_sign == 0))
     break;

   local_precision = dplaces + tmp0->m_apm_exponent;

   if (local_precision < 20)
     local_precision = 20;

   m_apm_set_long(tmp1, m1);
   m_apm_round(term, local_precision, tmp0);
   m_apm_divide(tmp0, local_precision, term, tmp1);
   m_apm_add(tmp1, tmpS, tmp0);
   m_apm_copy(tmpS, tmp1);
   m1 += 2;
  }

m_apm_multiply(tmp0, MM_Two, tmpS);
m_apm_round(rr, places, tmp0);

M_restore_stack(5);                    /* restore the 5 locals we used here */
}
Example #4
0
/*
 *      find log(N)
 *
 *      if places < 360
 *         solve with cubically convergent algorithm above
 *
 *      else
 *
 *      let 'X' be 'close' to the solution   (we use ~110 decimal places)
 *
 *      let Y = N * exp(-X) - 1
 *
 *	then
 *
 *	log(N) = X + log(1 + Y)
 *
 *      since 'Y' will be small, we can use the efficient log_near_1 algorithm.
 *
 */
void	M_log_basic_iteration(M_APM rr, int places, M_APM nn)
{
M_APM   tmp0, tmp1, tmp2, tmpX;

if (places < 360)
  {
   M_log_solve_cubic(rr, places, nn);
  }
else
  {
   tmp0 = M_get_stack_var();
   tmp1 = M_get_stack_var();
   tmp2 = M_get_stack_var();
   tmpX = M_get_stack_var();
   
   M_log_solve_cubic(tmpX, 110, nn);
   
   m_apm_negate(tmp0, tmpX);
   m_apm_exp(tmp1, (places + 8), tmp0);
   m_apm_multiply(tmp2, tmp1, nn);
   m_apm_subtract(tmp1, tmp2, MM_One);
   
   M_log_near_1(tmp0, (places - 104), tmp1);
   
   m_apm_add(tmp1, tmpX, tmp0);
   m_apm_round(rr, places, tmp1);
   
   M_restore_stack(4);
  }
}
Example #5
0
/*
 *      arccosh(x) == log [ x + sqrt(x^2 - 1) ]
 *
 *      x >= 1.0
 */
void	m_apm_arccosh(M_APM rr, int places, M_APM aa)
{
M_APM	tmp1, tmp2;
int     ii;

ii = m_apm_compare(aa, MM_One);

if (ii == -1)       /* x < 1 */
  {
   M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_arccosh\', Argument < 1");
   M_set_to_zero(rr);
   return;
  }

tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();

m_apm_multiply(tmp1, aa, aa);
m_apm_subtract(tmp2, tmp1, MM_One);
m_apm_sqrt(tmp1, (places + 6), tmp2);
m_apm_add(tmp2, aa, tmp1);
m_apm_log(rr, places, tmp2);

M_restore_stack(2);
}
Example #6
0
/*
 *  compute X = (a * X + c) MOD m       where c = a
 */
void	m_apm_get_random(M_APM mrnd)
{

	if (M_firsttime2)         /* use the system time as the initial seed value */
	{
		M_firsttime2 = FALSE;

		M_rnd_aa = m_apm_init();
		M_rnd_XX = m_apm_init();
		M_rnd_mm = m_apm_init();
		M_rtmp0  = m_apm_init();
		M_rtmp1  = m_apm_init();

		/* set the multiplier M_rnd_aa and M_rnd_mm */

		m_apm_set_string(M_rnd_aa, "716805947629621");
		m_apm_set_string(M_rnd_mm, "1.0E15");

		M_get_rnd_seed(M_rnd_XX);
	}

	m_apm_multiply(M_rtmp0, M_rnd_XX, M_rnd_aa);
	m_apm_add(M_rtmp1, M_rtmp0, M_rnd_aa);
	m_apm_integer_div_rem(M_rtmp0, M_rnd_XX, M_rtmp1, M_rnd_mm);
	m_apm_copy(mrnd, M_rnd_XX);
	mrnd->m_apm_exponent -= 15;
}
Example #7
0
/*
        Calculate arctan using the identity :

                                      x
        arctan (x) == arcsin [ --------------- ]
                                sqrt(1 + x^2)

*/
void	m_apm_arctan(M_APM rr, int places, M_APM xx)
{
M_APM   tmp8, tmp9;

if (xx->m_apm_sign == 0)			/* input == 0 ?? */
  {
   M_set_to_zero(rr);
   return;
  }

if (xx->m_apm_exponent <= -4)			/* input close to 0 ?? */
  {
   M_arctan_near_0(rr, places, xx);
   return;
  }

if (xx->m_apm_exponent >= 4)			/* large input */
  {
   M_arctan_large_input(rr, places, xx);
   return;
  }

tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();

m_apm_multiply(tmp9, xx, xx);
m_apm_add(tmp8, tmp9, MM_One);
m_apm_sqrt(tmp9, (places + 6), tmp8);
m_apm_divide(tmp8, (places + 6), xx, tmp9);
m_apm_arcsin(rr, places, tmp8);
M_restore_stack(2);
}
Example #8
0
/*
 *      arctanh(x) == 0.5 * log [ (1 + x) / (1 - x) ]
 *
 *      |x| < 1.0
 */
void	m_apm_arctanh(M_APM rr, int places, M_APM aa)
{
M_APM	tmp1, tmp2, tmp3;
int     ii, local_precision;

tmp1 = M_get_stack_var();

m_apm_absolute_value(tmp1, aa);

ii = m_apm_compare(tmp1, MM_One);

if (ii >= 0)       /* |x| >= 1.0 */
  {
   M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_arctanh\', |Argument| >= 1");
   M_set_to_zero(rr);
   M_restore_stack(1);
   return;
  }

tmp2 = M_get_stack_var();
tmp3 = M_get_stack_var();

local_precision = places + 8;

m_apm_add(tmp1, MM_One, aa);
m_apm_subtract(tmp2, MM_One, aa);
m_apm_divide(tmp3, local_precision, tmp1, tmp2);
m_apm_log(tmp2, local_precision, tmp3);
m_apm_multiply(tmp1, tmp2, MM_0_5);
m_apm_round(rr, places, tmp1);

M_restore_stack(3);
}
Example #9
0
/*
 *      arcsinh(x) == log [ x + sqrt(x^2 + 1) ]
 *
 *      also, use arcsinh(-x) == -arcsinh(x)
 */
void	m_apm_arcsinh(M_APM rr, int places, M_APM aa)
{
M_APM	tmp0, tmp1, tmp2;

/* result is 0 if input is 0 */

if (aa->m_apm_sign == 0)
  {
   M_set_to_zero(rr);
   return;
  }

tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();

m_apm_absolute_value(tmp0, aa);
m_apm_multiply(tmp1, tmp0, tmp0);
m_apm_add(tmp2, tmp1, MM_One);
m_apm_sqrt(tmp1, (places + 6), tmp2);
m_apm_add(tmp2, tmp0, tmp1);
m_apm_log(rr, places, tmp2);

rr->m_apm_sign = aa->m_apm_sign; 			  /* fix final sign */

M_restore_stack(3);
}
Example #10
0
void	M_log_solve_cubic(M_APM rr, int places, M_APM nn)
{
M_APM   tmp0, tmp1, tmp2, tmp3, guess;
int	ii, maxp, tolerance, local_precision;

guess = M_get_stack_var();
tmp0  = M_get_stack_var();
tmp1  = M_get_stack_var();
tmp2  = M_get_stack_var();
tmp3  = M_get_stack_var();

M_get_log_guess(guess, nn);

tolerance       = -(places + 4);
maxp            = places + 16;
local_precision = 18;

/*    Use the following iteration to solve for log :

                        exp(X) - N 
      X     =  X - 2 * ------------
       n+1              exp(X) + N 

   
      this is a cubically convergent algorithm 
      (each iteration yields 3X more digits)
*/

ii = 0;

while (TRUE)
  {
   m_apm_exp(tmp1, local_precision, guess);

   m_apm_subtract(tmp3, tmp1, nn);
   m_apm_add(tmp2, tmp1, nn);

   m_apm_divide(tmp1, local_precision, tmp3, tmp2);
   m_apm_multiply(tmp0, MM_Two, tmp1);
   m_apm_subtract(tmp3, guess, tmp0);

   if (ii != 0)
     {
      if (((3 * tmp0->m_apm_exponent) < tolerance) || (tmp0->m_apm_sign == 0))
        break;
     }

   m_apm_round(guess, local_precision, tmp3);

   local_precision *= 3;

   if (local_precision > maxp)
     local_precision = maxp;

   ii = 1;
  }

m_apm_round(rr, places, tmp3);
M_restore_stack(5);
}
Example #11
0
/*
	compute  int *n  = round_to_nearest_int(a / log(2))
	         M_APM b = MAPM version of *n

        returns      0: OK
		 -1, 1: failure
*/
int	M_exp_compute_nn(int *n, M_APM b, M_APM a)
{
M_APM	tmp0, tmp1;
void	*vp;
char    *cp, sbuf[48];
int	kk;

*n   = 0;
vp   = NULL;
cp   = sbuf;
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();

/* find 'n' and convert it to a normal C int            */
/* we just need an approx 1/log(2) for this calculation */

m_apm_multiply(tmp1, a, MM_exp_log2R);

/* round to the nearest int */

if (tmp1->m_apm_sign >= 0)
  {
   m_apm_add(tmp0, tmp1, MM_0_5);
   m_apm_floor(tmp1, tmp0);
  }
else
  {
   m_apm_subtract(tmp0, tmp1, MM_0_5);
   m_apm_ceil(tmp1, tmp0);
  }

kk = tmp1->m_apm_exponent;
if (kk >= 42)
  {
   if ((vp = (void *)MAPM_MALLOC((kk + 16) * sizeof(char))) == NULL)
     {
      /* fatal, this does not return */

      M_apm_log_error_msg(M_APM_FATAL, "\'M_exp_compute_nn\', Out of memory");
     }

   cp = (char *)vp;
  }

m_apm_to_integer_string(cp, tmp1);
*n = atoi(cp);

m_apm_set_long(b, (long)(*n));

kk = m_apm_compare(b, tmp1);

if (vp != NULL)
  MAPM_FREE(vp);

M_restore_stack(2);
return(kk);
}
Example #12
0
/*
 *	check if our local copy of PI is precise enough
 *	for our purpose. if not, calculate PI so it's
 *	as precise as desired, accurate to 'places' decimal
 *	places.
 */
void	M_check_PI_places(int places)
{
int     dplaces;

dplaces = places + 2;

if (dplaces > MM_lc_PI_digits)
  {
   MM_lc_PI_digits = dplaces + 2;

   /* compute PI using the AGM  (see right below) */

   M_calculate_PI_AGM(MM_lc_PI, (dplaces + 5));

   m_apm_multiply(MM_lc_HALF_PI, MM_0_5, MM_lc_PI);
   m_apm_multiply(MM_lc_2_PI, MM_Two, MM_lc_PI);
  }
}
Example #13
0
void	M_limit_angle_to_pi(M_APM rr, int places, M_APM aa)
{
	M_APM	tmp7, tmp8, tmp9;

	M_check_PI_places(places);

	tmp9 = M_get_stack_var();
	m_apm_copy(tmp9, MM_lc_PI);

	if (m_apm_compare(aa, tmp9) == 1)       /*  > PI  */
	{
		tmp7 = M_get_stack_var();
		tmp8 = M_get_stack_var();

		m_apm_add(tmp7, aa, tmp9);
		m_apm_integer_divide(tmp9, tmp7, MM_lc_2_PI);
		m_apm_multiply(tmp8, tmp9, MM_lc_2_PI);
		m_apm_subtract(tmp9, aa, tmp8);
		m_apm_round(rr, places, tmp9);

		M_restore_stack(3);
		return;
	}

	tmp9->m_apm_sign = -1;
	if (m_apm_compare(aa, tmp9) == -1)       /*  < -PI  */
	{
		tmp7 = M_get_stack_var();
		tmp8 = M_get_stack_var();

		m_apm_add(tmp7, aa, tmp9);
		m_apm_integer_divide(tmp9, tmp7, MM_lc_2_PI);
		m_apm_multiply(tmp8, tmp9, MM_lc_2_PI);
		m_apm_subtract(tmp9, aa, tmp8);
		m_apm_round(rr, places, tmp9);

		M_restore_stack(3);
		return;
	}

	m_apm_copy(rr, aa);
	M_restore_stack(1);
}
Example #14
0
/*
 *     calculate the multiple angle identity for cos (4x)
 * 
 *     cos (4x) == 8 * [ cos^4 (x)  -  cos^2 (x) ]  +  1
 */
void	M_4x_do_it(M_APM rr, int places, M_APM xx)
{
M_APM   tmp0, tmp1, t2, t4;

tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
t2   = M_get_stack_var();
t4   = M_get_stack_var();

m_apm_multiply(tmp1, xx, xx);
m_apm_round(t2, (places + 4), tmp1);     /* x ^ 2 */
m_apm_multiply(t4, t2, t2);              /* x ^ 4 */

m_apm_subtract(tmp0, t4, t2);
m_apm_multiply(tmp1, tmp0, MM_5x_Eight);
m_apm_add(tmp0, MM_One, tmp1);
m_apm_round(rr, places, tmp0);
M_restore_stack(4);
}
Example #15
0
/*
 *   compute  r = sqrt(1 - a ^ 2).
 */
void	M_cos_to_sin(M_APM r, int places, M_APM a)
{
M_APM	tmp1, tmp2;

tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();

m_apm_multiply(tmp1, a, a);
m_apm_subtract(tmp2, MM_One, tmp1);
m_apm_sqrt(r, places, tmp2);
M_restore_stack(2);
}
Example #16
0
/*
 *     calculate the multiple angle identity for sin (5x)
 *
 *     sin (5x) == 16 * sin^5 (x)  -  20 * sin^3 (x)  +  5 * sin(x)  
 */
void	M_5x_do_it(M_APM rr, int places, M_APM xx)
{
M_APM   tmp0, tmp1, t2, t3, t5;

tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
t2   = M_get_stack_var();
t3   = M_get_stack_var();
t5   = M_get_stack_var();

m_apm_multiply(tmp1, xx, xx);
m_apm_round(t2, (places + 4), tmp1);     /* x ^ 2 */

m_apm_multiply(tmp1, t2, xx);
m_apm_round(t3, (places + 4), tmp1);     /* x ^ 3 */

m_apm_multiply(t5, t2, t3);              /* x ^ 5 */

m_apm_multiply(tmp0, xx, MM_Five);
m_apm_multiply(tmp1, t5, MM_5x_Sixteen);
m_apm_add(t2, tmp0, tmp1);
m_apm_multiply(tmp1, t3, MM_5x_Twenty);
m_apm_subtract(tmp0, t2, tmp1);

m_apm_round(rr, places, tmp0);
M_restore_stack(5);
}
Example #17
0
void	m_apm_integer_div_rem(M_APM qq, M_APM rr, M_APM aa, M_APM bb)
{
 if (aa->m_apm_error || bb->m_apm_error)
   {
     M_set_to_error(rr);
     M_set_to_error(qq);
     return;
   }

m_apm_integer_divide(qq, aa, bb);
m_apm_multiply(M_div_tmp7, qq, bb);
m_apm_subtract(rr, aa, M_div_tmp7);
}
Example #18
0
void	m_apm_lcm(M_APM r, M_APM u, M_APM v)
{
M_APM   tmpN, tmpG;

tmpN = M_get_stack_var();
tmpG = M_get_stack_var();

m_apm_multiply(tmpN, u, v);
m_apm_gcd(tmpG, u, v);
m_apm_integer_divide(r, tmpN, tmpG);

M_restore_stack(2);
}
Example #19
0
void	m_apm_divide(M_APM rr, int places, M_APM aa, M_APM bb)
{
M_APM   tmp0, tmp1;
int     sn, nexp, dplaces;

sn = aa->m_apm_sign * bb->m_apm_sign;

if (sn == 0)                  /* one number is zero, result is zero */
  {
   if (bb->m_apm_sign == 0)
     {
      M_apm_log_error_msg(M_APM_RETURN, 
                          "Warning! ... \'m_apm_divide\', Divide by 0");
     }

   M_set_to_zero(rr);
   return;
  }

/*
 *    Use the original 'Knuth' method for smaller divides. On the
 *    author's system, this was the *approx* break even point before
 *    the reciprocal method used below became faster.
 */

if (places < 250)
  {
   M_apm_sdivide(rr, places, aa, bb);
   return;
  }

/* mimic the decimal place behavior of the original divide */

nexp = aa->m_apm_exponent - bb->m_apm_exponent;

if (nexp > 0)
  dplaces = nexp + places;
else
  dplaces = places;

tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();

m_apm_reciprocal(tmp0, (dplaces + 8), bb);
m_apm_multiply(tmp1, tmp0, aa);
m_apm_round(rr, dplaces, tmp1);

M_restore_stack(2);
}
Example #20
0
void	M_5x_sin(M_APM r, int places, M_APM x)
{
M_APM   tmp8, tmp9;

tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();

m_apm_multiply(tmp9, x, MM_5x_125R);        /* 1 / (5*5*5) */
M_raw_sin(tmp8, (places + 6), tmp9);
M_5x_do_it(tmp9, (places + 4), tmp8);
M_5x_do_it(tmp8, (places + 4), tmp9);
M_5x_do_it(r, places, tmp8);

M_restore_stack(2);
}
Example #21
0
/*
        Calls the LOG function. The formula used is :

        log10(x)  =  A * log(x) where A = log  (e)  [0.43429448190325...]
                                             10
*/
void	m_apm_log10(M_APM rr, int places, M_APM aa)
{
int     dplaces;
M_APM   tmp8, tmp9;

tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();

dplaces = places + 4;
M_check_log_places(dplaces + 45);

m_apm_log(tmp9, dplaces, aa);
m_apm_multiply(tmp8, tmp9, MM_lc_log10R);
m_apm_round(rr, places, tmp8);
M_restore_stack(2);                    /* restore the 2 locals we used here */
}
Example #22
0
void	m_apm_lcm(M_APM r, M_APM u, M_APM v)
{
M_APM   tmpN, tmpG;
 if (u->m_apm_error || v->m_apm_error)
   {
     M_set_to_error(r);
     return;
   }

tmpN = M_get_stack_var();
tmpG = M_get_stack_var();

m_apm_multiply(tmpN, u, v);
m_apm_gcd(tmpG, u, v);
m_apm_integer_divide(r, tmpN, tmpG);

M_restore_stack(2);
}
Example #23
0
/*
	calculate the exponential function using the following series :

                              x^2     x^3     x^4     x^5
	exp(x) == 1  +  x  +  ---  +  ---  +  ---  +  ---  ...
                               2!      3!      4!      5!

*/
void	M_raw_exp(M_APM rr, int places, M_APM xx)
{
M_APM   tmp0, digit, term;
int	tolerance,  local_precision, prev_exp;
long    m1;

tmp0  = M_get_stack_var();
term  = M_get_stack_var();
digit = M_get_stack_var();

local_precision = places + 8;
tolerance       = -(places + 4);
prev_exp        = 0;

m_apm_add(rr, MM_One, xx);
m_apm_copy(term, xx);

m1 = 2L;

while (TRUE)
  {
   m_apm_set_long(digit, m1);
   m_apm_multiply(tmp0, term, xx);
   m_apm_divide(term, local_precision, tmp0, digit);
   m_apm_add(tmp0, rr, term);
   m_apm_copy(rr, tmp0);

   if ((term->m_apm_exponent < tolerance) || (term->m_apm_sign == 0))
     break;

   if (m1 != 2L)
     {
      local_precision = local_precision + term->m_apm_exponent - prev_exp;

      if (local_precision < 20)
        local_precision = 20;
     }

   prev_exp = term->m_apm_exponent;
   m1++;
  }

M_restore_stack(3);                    /* restore the 3 locals we used here */
}
Example #24
0
/*
 *      cosh(x) == 0.5 * [ exp(x) + exp(-x) ]
 */
void	m_apm_cosh(M_APM rr, int places, M_APM aa)
{
M_APM	tmp1, tmp2, tmp3;
int     local_precision;

tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
tmp3 = M_get_stack_var();

local_precision = places + 4;

m_apm_exp(tmp1, local_precision, aa);
m_apm_reciprocal(tmp2, local_precision, tmp1);
m_apm_add(tmp3, tmp1, tmp2);
m_apm_multiply(tmp1, tmp3, MM_0_5);
m_apm_round(rr, places, tmp1);

M_restore_stack(3);
}
Example #25
0
/*
 *	check if our local copy of log(2) & log(10) is precise
 *      enough for our purpose. if not, calculate them so it's
 *	as precise as desired, accurate to at least 'places'.
 */
void	M_check_log_places(int places)
{
M_APM   tmp6, tmp7, tmp8, tmp9;
int     dplaces;

dplaces = places + 4;

if (dplaces > MM_lc_log_digits)
  {
   MM_lc_log_digits = dplaces + 4;
   
   tmp6 = M_get_stack_var();
   tmp7 = M_get_stack_var();
   tmp8 = M_get_stack_var();
   tmp9 = M_get_stack_var();
   
   dplaces += 6 + (int)log10((double)places);
   
   m_apm_copy(tmp7, MM_One);
   tmp7->m_apm_exponent = -places;
   
   M_log_AGM_R_func(tmp8, dplaces, MM_One, tmp7);
   
   m_apm_multiply(tmp6, tmp7, MM_0_5);
   
   M_log_AGM_R_func(tmp9, dplaces, MM_One, tmp6);
   
   m_apm_subtract(MM_lc_log2, tmp9, tmp8);               /* log(2) */

   tmp7->m_apm_exponent -= 1;                            /* divide by 10 */

   M_log_AGM_R_func(tmp9, dplaces, MM_One, tmp7);

   m_apm_subtract(MM_lc_log10, tmp9, tmp8);              /* log(10) */
   m_apm_reciprocal(MM_lc_log10R, dplaces, MM_lc_log10); /* 1 / log(10) */

   M_restore_stack(4);
  }
}
Example #26
0
int main(int argc, char *argv[])
{
char	 version_info[80];
int      ct;
				/* declare the M_APM variables ... */
M_APM    aa_mapm;
M_APM    bb_mapm;
M_APM    cc_mapm;
M_APM    dd_mapm;

if (argc < 2)
  {
   m_apm_lib_short_version(version_info);

   fprintf(stdout,
      "Usage: primenum number\t\t\t[Version 1.3, MAPM Version %s]\n",
      	      version_info);
   fprintf(stdout,
      "       find the first 10 prime numbers starting with \'number\'\n");

   exit(4);
  }
				/* now initialize the M_APM variables ... */
aa_mapm = m_apm_init();
bb_mapm = m_apm_init();
cc_mapm = m_apm_init();
dd_mapm = m_apm_init();

init_working_mapm();

m_apm_set_string(dd_mapm, argv[1]);

/*
 *  if input < 3, set start point = 3
 */

if (m_apm_compare(dd_mapm, MM_Three) == -1)
  {
   m_apm_copy(dd_mapm, MM_Three);
  }

/*
 *  make sure we start with an odd integer
 */

m_apm_integer_divide(aa_mapm, dd_mapm, MM_Two);
m_apm_multiply(bb_mapm, MM_Two, aa_mapm);
m_apm_add(aa_mapm, MM_One, bb_mapm);

ct = 0;

while (TRUE)
  {
   if (is_number_prime(aa_mapm))
     {
      m_apm_to_integer_string(buffer, aa_mapm);
      fprintf(stdout,"%s\n",buffer);

      if (++ct == 10)
        break;
     }

   m_apm_add(cc_mapm, MM_Two, aa_mapm);
   m_apm_copy(aa_mapm, cc_mapm);
  }

free_working_mapm();

m_apm_free(aa_mapm);
m_apm_free(bb_mapm);
m_apm_free(cc_mapm);
m_apm_free(dd_mapm);

m_apm_free_all_mem();

exit(0);
}
Example #27
0
void	m_apm_sqrt(M_APM rr, int places, M_APM aa)
{
M_APM   last_x, guess, tmpN, tmp7, tmp8, tmp9;
int	ii, bflag, nexp, tolerance, dplaces;

if (aa->m_apm_sign <= 0)
  {
   if (aa->m_apm_sign == -1)
     {
      M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_sqrt\', Negative argument");
     }

   M_set_to_zero(rr);
   return;
  }

last_x = M_get_stack_var();
guess  = M_get_stack_var();
tmpN   = M_get_stack_var();
tmp7   = M_get_stack_var();
tmp8   = M_get_stack_var();
tmp9   = M_get_stack_var();

m_apm_copy(tmpN, aa);

/* 
    normalize the input number (make the exponent near 0) so
    the 'guess' function will not over/under flow on large
    magnitude exponents.
*/

nexp = aa->m_apm_exponent / 2;
tmpN->m_apm_exponent -= 2 * nexp;

M_get_sqrt_guess(guess, tmpN);    /* actually gets 1/sqrt guess */

tolerance = places + 4;
dplaces   = places + 16;
bflag     = FALSE;

m_apm_negate(last_x, MM_Ten);

/*   Use the following iteration to calculate 1 / sqrt(N) :

         X    =  0.5 * X * [ 3 - N * X^2 ]
          n+1                    
*/

ii = 0;

while (TRUE)
  {
   m_apm_multiply(tmp9, tmpN, guess);
   m_apm_multiply(tmp8, tmp9, guess);
   m_apm_round(tmp7, dplaces, tmp8);
   m_apm_subtract(tmp9, MM_Three, tmp7);
   m_apm_multiply(tmp8, tmp9, guess);
   m_apm_multiply(tmp9, tmp8, MM_0_5);

   if (bflag)
     break;

   m_apm_round(guess, dplaces, tmp9);

   /* force at least 2 iterations so 'last_x' has valid data */

   if (ii != 0)
     {
      m_apm_subtract(tmp7, guess, last_x);

      if (tmp7->m_apm_sign == 0)
        break;

      /* 
       *   if we are within a factor of 4 on the error term,
       *   we will be accurate enough after the *next* iteration
       *   is complete.  (note that the sign of the exponent on 
       *   the error term will be a negative number).
       */

      if ((-4 * tmp7->m_apm_exponent) > tolerance)
        bflag = TRUE;
     }

   m_apm_copy(last_x, guess);
   ii++;
  }

/*
 *    multiply by the starting number to get the final
 *    sqrt and then adjust the exponent since we found
 *    the sqrt of the normalized number.
 */

m_apm_multiply(tmp8, tmp9, tmpN);
m_apm_round(rr, places, tmp8);
rr->m_apm_exponent += nexp;

M_restore_stack(6);
}
Example #28
0
void	m_apm_exp(M_APM r, int places, M_APM x)
{
M_APM   tmp7, tmp8, tmp9;
int	dplaces, nn, ii;

if (MM_firsttime1)
  {
   MM_firsttime1 = FALSE;

   MM_exp_log2R = m_apm_init();
   MM_exp_512R  = m_apm_init();

   m_apm_set_string(MM_exp_log2R, "1.44269504089");   /* ~ 1 / log(2) */
   m_apm_set_string(MM_exp_512R,  "1.953125E-3");     /*   1 / 512    */
  }

tmp7 = M_get_stack_var();
tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();

if (x->m_apm_sign == 0)		/* if input == 0, return '1' */
  {
   m_apm_copy(r, MM_One);
   M_restore_stack(3);
   return;
  }

if (x->m_apm_exponent <= -3)  /* already small enough so call _raw directly */
  {
   M_raw_exp(tmp9, (places + 6), x);
   m_apm_round(r, places, tmp9);
   M_restore_stack(3);
   return;
  }

/*
    From David H. Bailey's MPFUN Fortran package :

    exp (t) =  (1 + r + r^2 / 2! + r^3 / 3! + r^4 / 4! ...) ^ q * 2 ^ n

    where q = 256, r = t' / q, t' = t - n Log(2) and where n is chosen so
    that -0.5 Log(2) < t' <= 0.5 Log(2).  Reducing t mod Log(2) and
    dividing by 256 insures that -0.001 < r <= 0.001, which accelerates
    convergence in the above series.

    I use q = 512 and also limit how small 'r' can become. The 'r' used
    here is limited in magnitude from 1.95E-4 < |r| < 1.35E-3. Forcing
    'r' into a narrow range keeps the algorithm 'well behaved'.

    ( the range is [0.1 / 512] to [log(2) / 512] )
*/

if (M_exp_compute_nn(&nn, tmp7, x) != 0)
  {
   M_apm_log_error_msg(M_APM_RETURN, 
      "\'m_apm_exp\', Input too large, Overflow");

   M_set_to_zero(r);
   M_restore_stack(3);
   return;
  }

dplaces = places + 8;

/* check to make sure our log(2) is accurate enough */

M_check_log_places(dplaces);

m_apm_multiply(tmp8, tmp7, MM_lc_log2);
m_apm_subtract(tmp7, x, tmp8);

/*
 *     guarantee that |tmp7| is between 0.1 and 0.9999999....
 *     (in practice, the upper limit only reaches log(2), 0.693... )
 */

while (TRUE)
  {
   if (tmp7->m_apm_sign != 0)
     {
      if (tmp7->m_apm_exponent == 0)
        break;
     }
     
   if (tmp7->m_apm_sign >= 0)
     {
      nn++;
      m_apm_subtract(tmp8, tmp7, MM_lc_log2);
      m_apm_copy(tmp7, tmp8);
     }
   else
     {
      nn--;
      m_apm_add(tmp8, tmp7, MM_lc_log2);
      m_apm_copy(tmp7, tmp8);
     }
  }

m_apm_multiply(tmp9, tmp7, MM_exp_512R);

/* perform the series expansion ... */

M_raw_exp(tmp8, dplaces, tmp9);

/*
 *   raise result to the 512 power
 *
 *   note : x ^ 512  =  (((x ^ 2) ^ 2) ^ 2) ... 9 times
 */

ii = 9;

while (TRUE)
  {
   m_apm_multiply(tmp9, tmp8, tmp8);
   m_apm_round(tmp8, dplaces, tmp9);

   if (--ii == 0)
     break;
  }

/* now compute 2 ^ N */

m_apm_integer_pow(tmp7, dplaces, MM_Two, nn);

m_apm_multiply(tmp9, tmp7, tmp8);
m_apm_round(r, places, tmp9);

M_restore_stack(3);                    /* restore the 3 locals we used here */
}
Example #29
0
void	M_log_AGM_R_func(M_APM rr, int places, M_APM aa, M_APM bb)
{
M_APM   tmp1, tmp2, tmp3, tmp4, tmpC2, sum, pow_2, tmpA0, tmpB0;
int	tolerance, dplaces;

tmpA0 = M_get_stack_var();
tmpB0 = M_get_stack_var();
tmpC2 = M_get_stack_var();
tmp1  = M_get_stack_var();
tmp2  = M_get_stack_var();
tmp3  = M_get_stack_var();
tmp4  = M_get_stack_var();
sum   = M_get_stack_var();
pow_2 = M_get_stack_var();

tolerance = places + 8;
dplaces   = places + 16;

m_apm_copy(tmpA0, aa);
m_apm_copy(tmpB0, bb);
m_apm_copy(pow_2, MM_0_5);

m_apm_multiply(tmp1, aa, aa);		    /* 0.5 * [ a ^ 2 - b ^ 2 ] */
m_apm_multiply(tmp2, bb, bb);
m_apm_subtract(tmp3, tmp1, tmp2);
m_apm_multiply(sum, MM_0_5, tmp3);

while (TRUE)
  {
   m_apm_subtract(tmp1, tmpA0, tmpB0);      /* C n+1 = 0.5 * [ An - Bn ] */
   m_apm_multiply(tmp4, MM_0_5, tmp1);      /* C n+1 */
   m_apm_multiply(tmpC2, tmp4, tmp4);       /* C n+1 ^ 2 */

   /* do the AGM */

   m_apm_add(tmp1, tmpA0, tmpB0);
   m_apm_multiply(tmp3, MM_0_5, tmp1);

   m_apm_multiply(tmp2, tmpA0, tmpB0);
   m_apm_sqrt(tmpB0, dplaces, tmp2);

   m_apm_round(tmpA0, dplaces, tmp3);

   /* end AGM */

   m_apm_multiply(tmp2, MM_Two, pow_2);
   m_apm_copy(pow_2, tmp2);

   m_apm_multiply(tmp1, tmpC2, pow_2);
   m_apm_add(tmp3, sum, tmp1);

   if ((tmp1->m_apm_sign == 0) || 
      ((-2 * tmp1->m_apm_exponent) > tolerance))
     break;

   m_apm_round(sum, dplaces, tmp3);
  }

m_apm_subtract(tmp4, MM_One, tmp3);
m_apm_reciprocal(rr, places, tmp4);

M_restore_stack(9);
}
Example #30
0
void m_apm_square(M_APM x, M_APM y)    /*  x = y^2  */
{  
m_apm_multiply(x, y, y);
}