Beispiel #1
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;
}
Beispiel #2
0
static M_APM Bnew(lua_State *L)
{
 M_APM x=m_apm_init();
 lua_boxpointer(L,x);
 luaL_setmetatable(L,MYTYPE);
 return x;
}
Beispiel #3
0
M_APM 	m_apm_init_mt(void)
{
M_APM 	t;

	m_apm_enter();
	t=m_apm_init();
	m_apm_leave();
	return(t);
}
Beispiel #4
0
void	m_apm_cpp_precision(int digits)
{
	if (MM_lc_PI_digits == 0)
	{
		m_apm_free(m_apm_init());
	}

	if (digits >= 2)
		MM_cpp_min_precision = digits;
	else
		MM_cpp_min_precision = 2;
}
Beispiel #5
0
void    init_working_mapm()
{
M_limit = m_apm_init();
M_digit = m_apm_init();
M_quot  = m_apm_init();
M_rem   = m_apm_init();
M_tmp0  = m_apm_init();
M_tmp1  = m_apm_init();
}
Beispiel #6
0
M_APM apm_get(struct DeltaVariable *v)
{
	M_APM r = m_apm_init();
	
	if(v->type == DELTA_TYPE_NUMBER)
		m_apm_set_double(r, delta_cast_number(v));
	else {
		int release;
		struct DeltaVariable *arg = delta_cast_string(v, &release);
		
		if(release)
			m_apm_set_string(r, arg->value.ptr);
		else
			m_apm_set_string(r, delta_copy_string(arg->value.ptr));
	}
	
	return r;
}
Beispiel #7
0
void	M_fast_multiply(M_APM rr, M_APM aa, M_APM bb)
{
void	*vp;
int	ii, k, nexp, sign;

if (M_firsttimef)
  {
   M_firsttimef = FALSE;

   for (k=0; k < M_STACK_SIZE; k++)
     mul_stack_data_size[k] = 0;

   size_flag = M_get_sizeof_int();
   bit_limit = 8 * size_flag + 1;

   M_ain = m_apm_init();
   M_bin = m_apm_init();
  }

exp_stack_ptr   = -1;
M_mul_stack_ptr = -1;

m_apm_copy(M_ain, aa);
m_apm_copy(M_bin, bb);

sign = M_ain->m_apm_sign * M_bin->m_apm_sign;
nexp = M_ain->m_apm_exponent + M_bin->m_apm_exponent;

if (M_ain->m_apm_datalength >= M_bin->m_apm_datalength)
  ii = M_ain->m_apm_datalength;
else
  ii = M_bin->m_apm_datalength;

ii = (ii + 1) >> 1;
ii = M_next_power_of_2(ii);

/* Note: 'ii' must be >= 4 here. this is guaranteed 
   by the caller: m_apm_multiply
*/

k = 2 * ii;                   /* required size of result, in bytes  */

M_apm_pad(M_ain, k);          /* fill out the data so the number of */
M_apm_pad(M_bin, k);          /* bytes is an exact power of 2       */

if (k > rr->m_apm_malloclength)
  {
   if ((vp = MAPM_REALLOC(rr->m_apm_data, (k + 32))) == NULL)
     {
      /* fatal, this does not return */

      M_apm_log_error_msg(M_APM_FATAL, "\'M_fast_multiply\', Out of memory");
     }
  
   rr->m_apm_malloclength = k + 28;
   rr->m_apm_data = (UCHAR *)vp;
  }

#ifdef NO_FFT_MULTIPLY

M_fmul_div_conq(rr->m_apm_data, M_ain->m_apm_data, 
                                M_bin->m_apm_data, ii);
#else

/*
 *     if the numbers are *really* big, use the divide-and-conquer
 *     routine first until the numbers are small enough to be handled 
 *     by the FFT algorithm. If the numbers are already small enough,
 *     call the FFT multiplication now.
 *
 *     Note that 'ii' here is (and must be) an exact power of 2.
 */

if (size_flag == 2)   /* if still using 16 bit compilers .... */
  {
   M_fast_mul_fft(rr->m_apm_data, M_ain->m_apm_data, 
                                  M_bin->m_apm_data, ii);
  }
else                  /* >= 32 bit compilers */
  {
   if (ii > (MAX_FFT_BYTES + 2))
     {
      M_fmul_div_conq(rr->m_apm_data, M_ain->m_apm_data, 
                                      M_bin->m_apm_data, ii);
     }
   else
     {
      M_fast_mul_fft(rr->m_apm_data, M_ain->m_apm_data, 
                                     M_bin->m_apm_data, ii);
     }
  }

#endif

rr->m_apm_sign       = sign;
rr->m_apm_exponent   = nexp;
rr->m_apm_datalength = 4 * ii;

M_apm_normalize(rr);
}
Beispiel #8
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);
}
Beispiel #9
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 */
}
Beispiel #10
0
void	m_apm_add(M_APM r, M_APM a, M_APM b)
{
int	j, carry, sign, aexp, bexp, adigits, bdigits;

if (M_add_firsttime)
  {
   M_add_firsttime = FALSE;
   M_work1 = m_apm_init();
   M_work2 = m_apm_init();
  }

if (a->m_apm_sign == 0)
  {
   m_apm_copy(r,b);
   return;
  }

if (b->m_apm_sign == 0)
  {
   m_apm_copy(r,a);
   return;
  }
  
if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
  {
   b->m_apm_sign = 1;
   m_apm_subtract(r,a,b);
   b->m_apm_sign = -1;
   return;
  }

if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
  {
   a->m_apm_sign = 1;
   m_apm_subtract(r,b,a);
   a->m_apm_sign = -1;
   return;
  }

sign = a->m_apm_sign;         /* signs are the same, result will be same */

aexp = a->m_apm_exponent;
bexp = b->m_apm_exponent;

m_apm_copy(M_work1, a);
m_apm_copy(M_work2, b);

/*
 *  scale by at least 1 factor of 10 in case the MSB carrys
 */

if (aexp == bexp)
  {
   M_apm_scale(M_work1, 2);   /* shift 2 digits == 1 byte for efficiency */
   M_apm_scale(M_work2, 2);
  }
else
  {
   if (aexp > bexp)
     {
      M_apm_scale(M_work1, 2);
      M_apm_scale(M_work2, (aexp + 2 - bexp));
     }
   else            /*  aexp < bexp  */
     {
      M_apm_scale(M_work2, 2);
      M_apm_scale(M_work1, (bexp + 2 - aexp));
     }
  }

adigits = M_work1->m_apm_datalength;
bdigits = M_work2->m_apm_datalength;

if (adigits >= bdigits)
  {
   m_apm_copy(r, M_work1);
   j = (bdigits + 1) >> 1;
   carry = 0;

   while (TRUE)
     {
      j--;
      r->m_apm_data[j] += carry + M_work2->m_apm_data[j];

      if (r->m_apm_data[j] >= 100)
        {
         r->m_apm_data[j] -= 100;
	 carry = 1;
	}
      else
         carry = 0;

      if (j == 0) 
        break;
     }
  }
Beispiel #11
0
void	m_apm_trim_mem_usage()
{
m_apm_free_all_mem();
m_apm_free(m_apm_init());
}
Beispiel #12
0
void	m_apm_factorial(M_APM moutput, M_APM minput)
{
int     ii, nmul, ndigits, nd, jj, kk, mm, ct;
M_APM   array[NDIM];
M_APM   iprod1, iprod2, tmp1, tmp2;

/* return 1 for any input <= 1 */

if (m_apm_compare(minput, MM_One) <= 0)
  {
   m_apm_copy(moutput, MM_One);
   return;
  }

ct       = 0;
mm       = NDIM - 2;
ndigits  = 256;
nd       = ndigits - 20;
tmp1     = m_apm_init();
tmp2     = m_apm_init();
iprod1   = m_apm_init();
iprod2   = m_apm_init();
array[0] = m_apm_init();

m_apm_copy(tmp2, minput);

/* loop until multiply count-down has reached '2' */

while (TRUE)
  {
   m_apm_copy(iprod1, MM_One);

   /* 
    *   loop until the number of significant digits in this 
    *   partial result is slightly less than 256
    */

   while (TRUE)
     {
      m_apm_multiply(iprod2, iprod1, tmp2);

      m_apm_subtract(tmp1, tmp2, MM_One);

      m_apm_multiply(iprod1, iprod2, tmp1);

      /*
       *  I know, I know.  There just isn't a *clean* way 
       *  to break out of 2 nested loops.
       */

      if (m_apm_compare(tmp1, MM_Two) <= 0)
        goto PHASE2;

      m_apm_subtract(tmp2, tmp1, MM_One);

      if (iprod1->m_apm_datalength > nd)
        break;
     }

   if (ct == (NDIM - 1))
     {
      /* 
       *    if the array has filled up, start multiplying
       *    some of the partial products now.
       */

      m_apm_copy(tmp1, array[mm]);
      m_apm_multiply(array[mm], iprod1, tmp1);

      if (mm == 0)
        {
         mm = NDIM - 2;
	 ndigits = ndigits << 1;
         nd = ndigits - 20;
	}
      else
         mm--;
     }
   else
     {
      /* 
       *    store this partial product in the array
       *    and allocate the next array element
       */

      m_apm_copy(array[ct], iprod1);
      array[++ct] = m_apm_init();
     }
  }

PHASE2:

m_apm_copy(array[ct], iprod1);

kk = ct;

while (kk != 0)
  {
   ii = 0;
   jj = 0;
   nmul = (kk + 1) >> 1;

   while (TRUE)
     {
      /* must use tmp var when ii,jj point to same element */

      if (ii == 0)
        {
         m_apm_copy(tmp1, array[ii]);
         m_apm_multiply(array[jj], tmp1, array[ii+1]);
        }
      else
         m_apm_multiply(array[jj], array[ii], array[ii+1]);

      if (++jj == nmul)
        break;

      ii += 2;
     }

   if ((kk & 1) == 0)
     {
      jj = kk >> 1;
      m_apm_copy(array[jj], array[kk]);
     }

   kk = kk >> 1;
  }
Beispiel #13
0
void	M_apm_sdivide(M_APM r, int places, M_APM a, M_APM b)
{
int	j, k, m, b0, sign, nexp, indexr, icompare, iterations;
long    trial_numer;
void	*vp;

if (M_div_firsttime)
  {
   M_div_firsttime = FALSE;

   M_div_worka = m_apm_init();
   M_div_workb = m_apm_init();
   M_div_tmp7  = m_apm_init();
   M_div_tmp8  = m_apm_init();
   M_div_tmp9  = m_apm_init();
  }

sign = a->m_apm_sign * b->m_apm_sign;

if (sign == 0)      /* one number is zero, result is zero */
  {
   if (b->m_apm_sign == 0)
     {
      M_apm_log_error_msg(M_APM_RETURN, "\'M_apm_sdivide\', Divide by 0");
     }

   M_set_to_zero(r);
   return;
  }

/*
 *  Knuth step D1. Since base = 100, base / 2 = 50.
 *  (also make the working copies positive)
 */

if (b->m_apm_data[0] >= 50)
  {
   m_apm_absolute_value(M_div_worka, a);
   m_apm_absolute_value(M_div_workb, b);
  }
else       /* 'normal' step D1 */
  {
   k = 100 / (b->m_apm_data[0] + 1);
   m_apm_set_long(M_div_tmp9, (long)k);

   m_apm_multiply(M_div_worka, M_div_tmp9, a);
   m_apm_multiply(M_div_workb, M_div_tmp9, b);

   M_div_worka->m_apm_sign = 1;
   M_div_workb->m_apm_sign = 1;
  }

/* setup trial denominator for step D3 */

b0 = 100 * (int)M_div_workb->m_apm_data[0];

if (M_div_workb->m_apm_datalength >= 3)
  b0 += M_div_workb->m_apm_data[1];

nexp = M_div_worka->m_apm_exponent - M_div_workb->m_apm_exponent;

if (nexp > 0)
  iterations = nexp + places + 1;
else
  iterations = places + 1;

k = (iterations + 1) >> 1;     /* required size of result, in bytes */

if (k > r->m_apm_malloclength)
  {
   if ((vp = MAPM_REALLOC(r->m_apm_data, (k + 32))) == NULL)
     {
      /* fatal, this does not return */

      M_apm_log_error_msg(M_APM_FATAL, "\'M_apm_sdivide\', Out of memory");
     }
  
   r->m_apm_malloclength = k + 28;
   r->m_apm_data = (UCHAR *)vp;
  }

/* clear the exponent in the working copies */

M_div_worka->m_apm_exponent = 0;
M_div_workb->m_apm_exponent = 0;

/* if numbers are equal, ratio == 1.00000... */

if ((icompare = m_apm_compare(M_div_worka, M_div_workb)) == 0)
  {
   iterations = 1;
   r->m_apm_data[0] = 10;
   nexp++;
  }
else			           /* ratio not 1, do the real division */
  {
   if (icompare == 1)                        /* numerator > denominator */
     {
      nexp++;                           /* to adjust the final exponent */
      M_div_worka->m_apm_exponent += 1;     /* multiply numerator by 10 */
     }
   else                                      /* numerator < denominator */
     {
      M_div_worka->m_apm_exponent += 2;    /* multiply numerator by 100 */
     }

   indexr = 0;
   m      = 0;

   while (TRUE)
     {
      /*
       *  Knuth step D3. Only use the 3rd -> 6th digits if the number
       *  actually has that many digits.
       */

      trial_numer = 10000L * (long)M_div_worka->m_apm_data[0];
      
      if (M_div_worka->m_apm_datalength >= 5)
        {
         trial_numer += 100 * M_div_worka->m_apm_data[1]
                            + M_div_worka->m_apm_data[2];
	}
      else
        {
         if (M_div_worka->m_apm_datalength >= 3)
           trial_numer += 100 * M_div_worka->m_apm_data[1];
        }

      j = (int)(trial_numer / b0);

      /* 
       *    Since the library 'normalizes' all the results, we need
       *    to look at the exponent of the number to decide if we 
       *    have a lead in 0n or 00.
       */

      if ((k = 2 - M_div_worka->m_apm_exponent) > 0)
        {
	 while (TRUE)
	   {
	    j /= 10;
	    if (--k == 0)
	      break;
	   }
	}

      if (j == 100)     /* qhat == base ??      */
        j = 99;         /* if so, decrease by 1 */

      m_apm_set_long(M_div_tmp8, (long)j);
      m_apm_multiply(M_div_tmp7, M_div_tmp8, M_div_workb);

      /*
       *    Compare our q-hat (j) against the desired number.
       *    j is either correct, 1 too large, or 2 too large
       *    per Theorem B on pg 272 of Art of Compter Programming,
       *    Volume 2, 3rd Edition.
       *    
       *    The above statement is only true if using the 2 leading
       *    digits of the numerator and the leading digit of the 
       *    denominator. Since we are using the (3) leading digits
       *    of the numerator and the (2) leading digits of the 
       *    denominator, we eliminate the case where our q-hat is 
       *    2 too large, (and q-hat being 1 too large is quite remote).
       */

      if (m_apm_compare(M_div_tmp7, M_div_worka) == 1)
        {
	 j--;
         m_apm_subtract(M_div_tmp8, M_div_tmp7, M_div_workb);
         m_apm_copy(M_div_tmp7, M_div_tmp8);
	}

      /* 
       *  Since we know q-hat is correct, step D6 is unnecessary.
       *
       *  Store q-hat, step D5. Since D6 is unnecessary, we can 
       *  do D5 before D4 and decide if we are done.
       */

      r->m_apm_data[indexr++] = (UCHAR)j;    /* j == 'qhat' */
      m += 2;

      if (m >= iterations)
        break;

      /* step D4 */

      m_apm_subtract(M_div_tmp9, M_div_worka, M_div_tmp7);

      /*
       *  if the subtraction yields zero, the division is exact
       *  and we are done early.
       */

      if (M_div_tmp9->m_apm_sign == 0)
        {
	 iterations = m;
	 break;
	}

      /* multiply by 100 and re-save */
      M_div_tmp9->m_apm_exponent += 2;
      m_apm_copy(M_div_worka, M_div_tmp9);
     }
  }

r->m_apm_sign       = sign;
r->m_apm_exponent   = nexp;
r->m_apm_datalength = iterations;

M_apm_normalize(r);
}
Beispiel #14
0
void	M_init_trig_globals()
{
	MM_lc_PI_digits      = VALID_DECIMAL_PLACES;
	MM_lc_log_digits     = VALID_DECIMAL_PLACES;
	MM_cpp_min_precision = 30;

	MM_Zero          = m_apm_init();
	MM_One           = m_apm_init();
	MM_Two           = m_apm_init();
	MM_Three         = m_apm_init();
	MM_Four          = m_apm_init();
	MM_Five          = m_apm_init();
	MM_Ten           = m_apm_init();
	MM_0_5           = m_apm_init();
	MM_LOG_2_BASE_E  = m_apm_init();
	MM_LOG_3_BASE_E  = m_apm_init();
	MM_E             = m_apm_init();
	MM_PI            = m_apm_init();
	MM_HALF_PI       = m_apm_init();
	MM_2_PI          = m_apm_init();
	MM_lc_PI         = m_apm_init();
	MM_lc_HALF_PI    = m_apm_init();
	MM_lc_2_PI       = m_apm_init();
	MM_lc_log2       = m_apm_init();
	MM_lc_log10      = m_apm_init();
	MM_lc_log10R     = m_apm_init();
	MM_0_85          = m_apm_init();
	MM_5x_125R       = m_apm_init();
	MM_5x_64R        = m_apm_init();
	MM_5x_256R       = m_apm_init();
	MM_5x_Eight      = m_apm_init();
	MM_5x_Sixteen    = m_apm_init();
	MM_5x_Twenty     = m_apm_init();
	MM_LOG_E_BASE_10 = m_apm_init();
	MM_LOG_10_BASE_E = m_apm_init();

	m_apm_set_string(MM_One, "1");
	m_apm_set_string(MM_Two, "2");
	m_apm_set_string(MM_Three, "3");
	m_apm_set_string(MM_Four, "4");
	m_apm_set_string(MM_Five, "5");
	m_apm_set_string(MM_Ten, "10");
	m_apm_set_string(MM_0_5, "0.5");
	m_apm_set_string(MM_0_85, "0.85");

	m_apm_set_string(MM_5x_125R, "8.0E-3");
	m_apm_set_string(MM_5x_64R, "1.5625E-2");
	m_apm_set_string(MM_5x_256R, "3.90625E-3");
	m_apm_set_string(MM_5x_Eight, "8");
	m_apm_set_string(MM_5x_Sixteen, "16");
	m_apm_set_string(MM_5x_Twenty, "20");

	m_apm_set_string(MM_LOG_2_BASE_E, MM_cnst_log_2);
	m_apm_set_string(MM_LOG_3_BASE_E, MM_cnst_log_3);
	m_apm_set_string(MM_LOG_10_BASE_E, MM_cnst_log_10);
	m_apm_set_string(MM_LOG_E_BASE_10, MM_cnst_1_log_10);

	m_apm_set_string(MM_lc_log2, MM_cnst_log_2);
	m_apm_set_string(MM_lc_log10, MM_cnst_log_10);
	m_apm_set_string(MM_lc_log10R, MM_cnst_1_log_10);

	m_apm_set_string(MM_E, MM_cnst_E);
	m_apm_set_string(MM_PI, MM_cnst_PI);
	m_apm_multiply(MM_HALF_PI, MM_PI, MM_0_5);
	m_apm_multiply(MM_2_PI, MM_PI, MM_Two);

	m_apm_copy(MM_lc_PI, MM_PI);
	m_apm_copy(MM_lc_HALF_PI, MM_HALF_PI);
	m_apm_copy(MM_lc_2_PI, MM_2_PI);
}
Beispiel #15
0
/*
	Calculate the POW function by calling EXP :

                  Y      A                 
                 X   =  e    where A = Y * log(X)
*/
void	m_apm_pow(M_APM rr, int places, M_APM xx, M_APM yy)
{
int	iflag, pflag;
char    sbuf[64];
M_APM   tmp8, tmp9;

/* if yy == 0, return 1 */

if (yy->m_apm_sign == 0)
  {
   m_apm_copy(rr, MM_One);
   return;
  }

/* if xx == 0, return 0 */

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

if (M_size_flag == 0)       /* init locals on first call */
  {
   M_size_flag       = M_get_sizeof_int();
   M_last_log_digits = 0;
   M_last_xx_input   = m_apm_init();
   M_last_xx_log     = m_apm_init();
  }

/*
 *  if 'yy' is a small enough integer, call the more
 *  efficient _integer_pow function.
 */

if (m_apm_is_integer(yy))
  {
   iflag = FALSE;

   if (M_size_flag == 2)            /* 16 bit compilers */
     {
      if (yy->m_apm_exponent <= 4)
        iflag = TRUE;
     }
   else                             /* >= 32 bit compilers */
     {
      if (yy->m_apm_exponent <= 7)
        iflag = TRUE;
     }

   if (iflag)
     {
      m_apm_to_integer_string(sbuf, yy);
      m_apm_integer_pow(rr, places, xx, atoi(sbuf));
      return;
     }
  }

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

/*
 *    If parameter 'X' is the same this call as it 
 *    was the previous call, re-use the saved log 
 *    calculation from last time.
 */

pflag = FALSE;

if (M_last_log_digits >= places)
  {
   if (m_apm_compare(xx, M_last_xx_input) == 0)
     pflag = TRUE;
  }

if (pflag)
  {
   m_apm_round(tmp9, (places + 8), M_last_xx_log);
  }
else
  {
   m_apm_log(tmp9, (places + 8), xx);

   M_last_log_digits = places + 2;

   /* save the 'X' input value and the log calculation */

   m_apm_copy(M_last_xx_input, xx);
   m_apm_copy(M_last_xx_log, tmp9);
  }

m_apm_multiply(tmp8, tmp9, yy);
m_apm_exp(rr, places, tmp8);
M_restore_stack(2);                    /* restore the 2 locals we used here */
}