xref: /haiku/src/libs/mapm/mapmasn0.c (revision 59d799dabcba86f92658ddb402f634e262d9aae7)
1*59d799daSIngo Weinhold 
2*59d799daSIngo Weinhold /*
3*59d799daSIngo Weinhold  *  M_APM  -  mapmasn0.c
4*59d799daSIngo Weinhold  *
5*59d799daSIngo Weinhold  *  Copyright (C) 2000 - 2007   Michael C. Ring
6*59d799daSIngo Weinhold  *
7*59d799daSIngo Weinhold  *  Permission to use, copy, and distribute this software and its
8*59d799daSIngo Weinhold  *  documentation for any purpose with or without fee is hereby granted,
9*59d799daSIngo Weinhold  *  provided that the above copyright notice appear in all copies and
10*59d799daSIngo Weinhold  *  that both that copyright notice and this permission notice appear
11*59d799daSIngo Weinhold  *  in supporting documentation.
12*59d799daSIngo Weinhold  *
13*59d799daSIngo Weinhold  *  Permission to modify the software is granted. Permission to distribute
14*59d799daSIngo Weinhold  *  the modified code is granted. Modifications are to be distributed by
15*59d799daSIngo Weinhold  *  using the file 'license.txt' as a template to modify the file header.
16*59d799daSIngo Weinhold  *  'license.txt' is available in the official MAPM distribution.
17*59d799daSIngo Weinhold  *
18*59d799daSIngo Weinhold  *  This software is provided "as is" without express or implied warranty.
19*59d799daSIngo Weinhold  */
20*59d799daSIngo Weinhold 
21*59d799daSIngo Weinhold /*
22*59d799daSIngo Weinhold  *      $Id: mapmasn0.c,v 1.8 2007/12/03 01:49:49 mike Exp $
23*59d799daSIngo Weinhold  *
24*59d799daSIngo Weinhold  *      This file contains the 'ARC' family of functions; ARC-SIN,
25*59d799daSIngo Weinhold  *	ARC-COS, ARC-TAN when the input arg is very close to 0 (zero).
26*59d799daSIngo Weinhold  *
27*59d799daSIngo Weinhold  *      $Log: mapmasn0.c,v $
28*59d799daSIngo Weinhold  *      Revision 1.8  2007/12/03 01:49:49  mike
29*59d799daSIngo Weinhold  *      Update license
30*59d799daSIngo Weinhold  *
31*59d799daSIngo Weinhold  *      Revision 1.7  2003/06/02 16:51:13  mike
32*59d799daSIngo Weinhold  *      *** empty log message ***
33*59d799daSIngo Weinhold  *
34*59d799daSIngo Weinhold  *      Revision 1.6  2003/06/02 16:49:48  mike
35*59d799daSIngo Weinhold  *      tweak the decimal places
36*59d799daSIngo Weinhold  *
37*59d799daSIngo Weinhold  *      Revision 1.5  2003/06/02 16:47:39  mike
38*59d799daSIngo Weinhold  *      tweak arctan algorithm some more
39*59d799daSIngo Weinhold  *
40*59d799daSIngo Weinhold  *      Revision 1.4  2003/05/31 22:38:07  mike
41*59d799daSIngo Weinhold  *      optimize arctan by using fewer digits as subsequent
42*59d799daSIngo Weinhold  *      terms get smaller
43*59d799daSIngo Weinhold  *
44*59d799daSIngo Weinhold  *      Revision 1.3  2002/11/03 21:36:43  mike
45*59d799daSIngo Weinhold  *      Updated function parameters to use the modern style
46*59d799daSIngo Weinhold  *
47*59d799daSIngo Weinhold  *      Revision 1.2  2000/12/02 20:11:37  mike
48*59d799daSIngo Weinhold  *      add comments
49*59d799daSIngo Weinhold  *
50*59d799daSIngo Weinhold  *      Revision 1.1  2000/12/02 20:08:27  mike
51*59d799daSIngo Weinhold  *      Initial revision
52*59d799daSIngo Weinhold  */
53*59d799daSIngo Weinhold 
54*59d799daSIngo Weinhold #include "m_apm_lc.h"
55*59d799daSIngo Weinhold 
56*59d799daSIngo Weinhold /****************************************************************************/
57*59d799daSIngo Weinhold /*
58*59d799daSIngo Weinhold         Calculate arcsin using the identity :
59*59d799daSIngo Weinhold 
60*59d799daSIngo Weinhold                                       x
61*59d799daSIngo Weinhold         arcsin (x) == arctan [ --------------- ]
62*59d799daSIngo Weinhold                                 sqrt(1 - x^2)
63*59d799daSIngo Weinhold 
64*59d799daSIngo Weinhold */
M_arcsin_near_0(M_APM rr,int places,M_APM aa)65*59d799daSIngo Weinhold void	M_arcsin_near_0(M_APM rr, int places, M_APM aa)
66*59d799daSIngo Weinhold {
67*59d799daSIngo Weinhold M_APM   tmp5, tmp6;
68*59d799daSIngo Weinhold 
69*59d799daSIngo Weinhold tmp5 = M_get_stack_var();
70*59d799daSIngo Weinhold tmp6 = M_get_stack_var();
71*59d799daSIngo Weinhold 
72*59d799daSIngo Weinhold M_cos_to_sin(tmp5, (places + 8), aa);
73*59d799daSIngo Weinhold m_apm_divide(tmp6, (places + 8), aa, tmp5);
74*59d799daSIngo Weinhold M_arctan_near_0(rr, places, tmp6);
75*59d799daSIngo Weinhold 
76*59d799daSIngo Weinhold M_restore_stack(2);
77*59d799daSIngo Weinhold }
78*59d799daSIngo Weinhold /****************************************************************************/
79*59d799daSIngo Weinhold /*
80*59d799daSIngo Weinhold         Calculate arccos using the identity :
81*59d799daSIngo Weinhold 
82*59d799daSIngo Weinhold         arccos (x) == PI / 2 - arcsin (x)
83*59d799daSIngo Weinhold 
84*59d799daSIngo Weinhold */
M_arccos_near_0(M_APM rr,int places,M_APM aa)85*59d799daSIngo Weinhold void	M_arccos_near_0(M_APM rr, int places, M_APM aa)
86*59d799daSIngo Weinhold {
87*59d799daSIngo Weinhold M_APM   tmp1, tmp2;
88*59d799daSIngo Weinhold 
89*59d799daSIngo Weinhold tmp1 = M_get_stack_var();
90*59d799daSIngo Weinhold tmp2 = M_get_stack_var();
91*59d799daSIngo Weinhold 
92*59d799daSIngo Weinhold M_check_PI_places(places);
93*59d799daSIngo Weinhold M_arcsin_near_0(tmp1, (places + 4), aa);
94*59d799daSIngo Weinhold m_apm_subtract(tmp2, MM_lc_HALF_PI, tmp1);
95*59d799daSIngo Weinhold m_apm_round(rr, places, tmp2);
96*59d799daSIngo Weinhold 
97*59d799daSIngo Weinhold M_restore_stack(2);
98*59d799daSIngo Weinhold }
99*59d799daSIngo Weinhold /****************************************************************************/
100*59d799daSIngo Weinhold /*
101*59d799daSIngo Weinhold 	calculate arctan (x) with the following series:
102*59d799daSIngo Weinhold 
103*59d799daSIngo Weinhold                               x^3     x^5     x^7     x^9
104*59d799daSIngo Weinhold 	arctan (x)  =   x  -  ---  +  ---  -  ---  +  ---  ...
105*59d799daSIngo Weinhold                                3       5       7       9
106*59d799daSIngo Weinhold 
107*59d799daSIngo Weinhold */
M_arctan_near_0(M_APM rr,int places,M_APM aa)108*59d799daSIngo Weinhold void	M_arctan_near_0(M_APM rr, int places, M_APM aa)
109*59d799daSIngo Weinhold {
110*59d799daSIngo Weinhold M_APM   tmp0, tmp2, tmpR, tmpS, digit, term;
111*59d799daSIngo Weinhold int	tolerance, dplaces, local_precision;
112*59d799daSIngo Weinhold long    m1;
113*59d799daSIngo Weinhold 
114*59d799daSIngo Weinhold tmp0  = M_get_stack_var();
115*59d799daSIngo Weinhold tmp2  = M_get_stack_var();
116*59d799daSIngo Weinhold tmpR  = M_get_stack_var();
117*59d799daSIngo Weinhold tmpS  = M_get_stack_var();
118*59d799daSIngo Weinhold term  = M_get_stack_var();
119*59d799daSIngo Weinhold digit = M_get_stack_var();
120*59d799daSIngo Weinhold 
121*59d799daSIngo Weinhold tolerance = aa->m_apm_exponent - (places + 4);
122*59d799daSIngo Weinhold dplaces   = (places + 8) - aa->m_apm_exponent;
123*59d799daSIngo Weinhold 
124*59d799daSIngo Weinhold m_apm_copy(term, aa);
125*59d799daSIngo Weinhold m_apm_copy(tmpS, aa);
126*59d799daSIngo Weinhold m_apm_multiply(tmp0, aa, aa);
127*59d799daSIngo Weinhold m_apm_round(tmp2, (dplaces + 8), tmp0);
128*59d799daSIngo Weinhold 
129*59d799daSIngo Weinhold m1 = 1L;
130*59d799daSIngo Weinhold 
131*59d799daSIngo Weinhold while (TRUE)
132*59d799daSIngo Weinhold   {
133*59d799daSIngo Weinhold    /*
134*59d799daSIngo Weinhold     *   do the subtraction term
135*59d799daSIngo Weinhold     */
136*59d799daSIngo Weinhold 
137*59d799daSIngo Weinhold    m_apm_multiply(tmp0, term, tmp2);
138*59d799daSIngo Weinhold 
139*59d799daSIngo Weinhold    if ((tmp0->m_apm_exponent < tolerance) || (tmp0->m_apm_sign == 0))
140*59d799daSIngo Weinhold      {
141*59d799daSIngo Weinhold       m_apm_round(rr, places, tmpS);
142*59d799daSIngo Weinhold       break;
143*59d799daSIngo Weinhold      }
144*59d799daSIngo Weinhold 
145*59d799daSIngo Weinhold    local_precision = dplaces + tmp0->m_apm_exponent;
146*59d799daSIngo Weinhold 
147*59d799daSIngo Weinhold    if (local_precision < 20)
148*59d799daSIngo Weinhold      local_precision = 20;
149*59d799daSIngo Weinhold 
150*59d799daSIngo Weinhold    m1 += 2;
151*59d799daSIngo Weinhold    m_apm_set_long(digit, m1);
152*59d799daSIngo Weinhold    m_apm_round(term, local_precision, tmp0);
153*59d799daSIngo Weinhold    m_apm_divide(tmp0, local_precision, term, digit);
154*59d799daSIngo Weinhold    m_apm_subtract(tmpR, tmpS, tmp0);
155*59d799daSIngo Weinhold 
156*59d799daSIngo Weinhold    /*
157*59d799daSIngo Weinhold     *   do the addition term
158*59d799daSIngo Weinhold     */
159*59d799daSIngo Weinhold 
160*59d799daSIngo Weinhold    m_apm_multiply(tmp0, term, tmp2);
161*59d799daSIngo Weinhold 
162*59d799daSIngo Weinhold    if ((tmp0->m_apm_exponent < tolerance) || (tmp0->m_apm_sign == 0))
163*59d799daSIngo Weinhold      {
164*59d799daSIngo Weinhold       m_apm_round(rr, places, tmpR);
165*59d799daSIngo Weinhold       break;
166*59d799daSIngo Weinhold      }
167*59d799daSIngo Weinhold 
168*59d799daSIngo Weinhold    local_precision = dplaces + tmp0->m_apm_exponent;
169*59d799daSIngo Weinhold 
170*59d799daSIngo Weinhold    if (local_precision < 20)
171*59d799daSIngo Weinhold      local_precision = 20;
172*59d799daSIngo Weinhold 
173*59d799daSIngo Weinhold    m1 += 2;
174*59d799daSIngo Weinhold    m_apm_set_long(digit, m1);
175*59d799daSIngo Weinhold    m_apm_round(term, local_precision, tmp0);
176*59d799daSIngo Weinhold    m_apm_divide(tmp0, local_precision, term, digit);
177*59d799daSIngo Weinhold    m_apm_add(tmpS, tmpR, tmp0);
178*59d799daSIngo Weinhold   }
179*59d799daSIngo Weinhold 
180*59d799daSIngo Weinhold M_restore_stack(6);                    /* restore the 6 locals we used here */
181*59d799daSIngo Weinhold }
182*59d799daSIngo Weinhold /****************************************************************************/
183