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); }
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(); }