Exemple #1
0
void	m_apm_arcsin(M_APM r, int places, M_APM x)
{
M_APM   tmp0, tmp1, tmp2, tmp3, current_x;
int	ii, maxiter, maxp, tolerance, local_precision;

current_x = 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_apm_absolute_value(tmp0, x);

ii = m_apm_compare(tmp0, MM_One);

if (ii == 1)       /* |x| > 1 */
  {
   M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_arcsin\', |Argument| > 1");
   M_set_to_zero(r);
   M_restore_stack(5);
   return;
  }

if (ii == 0)       /* |x| == 1, arcsin = +/- PI / 2 */
  {
   M_check_PI_places(places);
   m_apm_round(r, places, MM_lc_HALF_PI);
   r->m_apm_sign = x->m_apm_sign;

   M_restore_stack(5);
   return;
  }

if (m_apm_compare(tmp0, MM_0_85) == 1)        /* check if > 0.85 */
  {
   M_cos_to_sin(tmp2, (places + 4), x);
   m_apm_arccos(r, places, tmp2);
   r->m_apm_sign = x->m_apm_sign;

   M_restore_stack(5);
   return;
  }

if (x->m_apm_sign == 0)			      /* input == 0 ?? */
  {
   M_set_to_zero(r);
   M_restore_stack(5);
   return;
  }

if (x->m_apm_exponent <= -4)		      /* input close to 0 ?? */
  {
   M_arcsin_near_0(r, places, x);
   M_restore_stack(5);
   return;
  }

tolerance       = -(places + 4);
maxp            = places + 8 - x->m_apm_exponent;
local_precision = 20 - x->m_apm_exponent;

/*
 *      compute the maximum number of iterations
 *	that should be needed to calculate to
 *	the desired accuracy.  [ constant below ~= 1 / log(2) ]
 */

maxiter = (int)(log((double)(places + 2)) * 1.442695) + 3;

if (maxiter < 5)
  maxiter = 5;

M_get_asin_guess(current_x, x);

/*    Use the following iteration to solve for arc-sin :

                      sin(X) - N
      X     =  X  -  ------------
       n+1              cos(X)
*/

ii = 0;

while (TRUE)
  {
   M_4x_cos(tmp1, local_precision, current_x);

   M_cos_to_sin(tmp2, local_precision, tmp1);
   if (tmp2->m_apm_sign != 0)
     tmp2->m_apm_sign = current_x->m_apm_sign;

   m_apm_subtract(tmp3, tmp2, x);
   m_apm_divide(tmp0, local_precision, tmp3, tmp1);

   m_apm_subtract(tmp2, current_x, tmp0);
   m_apm_copy(current_x, tmp2);

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

   if (++ii == maxiter)
     {
      M_apm_log_error_msg(M_APM_RETURN, 
            "\'m_apm_arcsin\', max iteration count reached");
      break;
     }

   local_precision *= 2;

   if (local_precision > maxp)
     local_precision = maxp;
  }

m_apm_round(r, places, current_x);
M_restore_stack(5);
}
Exemple #2
0
void	m_apm_arccos_mt(M_APM r, int places, M_APM x)
{
	m_apm_enter();
	m_apm_arccos(r,places,x);
	m_apm_leave();
}