xref: /haiku/src/libs/mapm/mapm_pow.c (revision 59d799dabcba86f92658ddb402f634e262d9aae7)
1*59d799daSIngo Weinhold 
2*59d799daSIngo Weinhold /*
3*59d799daSIngo Weinhold  *  M_APM  -  mapm_pow.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: mapm_pow.c,v 1.10 2007/12/03 01:46:07 mike Exp $
23*59d799daSIngo Weinhold  *
24*59d799daSIngo Weinhold  *      This file contains the POW function.
25*59d799daSIngo Weinhold  *
26*59d799daSIngo Weinhold  *      $Log: mapm_pow.c,v $
27*59d799daSIngo Weinhold  *      Revision 1.10  2007/12/03 01:46:07  mike
28*59d799daSIngo Weinhold  *      Update license
29*59d799daSIngo Weinhold  *
30*59d799daSIngo Weinhold  *      Revision 1.9  2002/11/05 23:39:42  mike
31*59d799daSIngo Weinhold  *      use new set_to_zero call
32*59d799daSIngo Weinhold  *
33*59d799daSIngo Weinhold  *      Revision 1.8  2002/11/03 22:20:59  mike
34*59d799daSIngo Weinhold  *      Updated function parameters to use the modern style
35*59d799daSIngo Weinhold  *
36*59d799daSIngo Weinhold  *      Revision 1.7  2001/07/16 19:24:26  mike
37*59d799daSIngo Weinhold  *      add function M_free_all_pow
38*59d799daSIngo Weinhold  *
39*59d799daSIngo Weinhold  *      Revision 1.6  2000/09/05 22:15:03  mike
40*59d799daSIngo Weinhold  *      minor tweak
41*59d799daSIngo Weinhold  *
42*59d799daSIngo Weinhold  *      Revision 1.5  2000/08/22 21:22:29  mike
43*59d799daSIngo Weinhold  *      if parameter yy is an integer, call the more
44*59d799daSIngo Weinhold  *      efficient _integer_pow function
45*59d799daSIngo Weinhold  *
46*59d799daSIngo Weinhold  *      Revision 1.4  2000/08/22 20:42:08  mike
47*59d799daSIngo Weinhold  *      compute more digits in the log calculation
48*59d799daSIngo Weinhold  *
49*59d799daSIngo Weinhold  *      Revision 1.3  2000/05/24 20:08:21  mike
50*59d799daSIngo Weinhold  *      update some comments
51*59d799daSIngo Weinhold  *
52*59d799daSIngo Weinhold  *      Revision 1.2  2000/05/23 23:20:11  mike
53*59d799daSIngo Weinhold  *      return 1 when input is 0^0.
54*59d799daSIngo Weinhold  *
55*59d799daSIngo Weinhold  *      Revision 1.1  2000/05/18 22:10:43  mike
56*59d799daSIngo Weinhold  *      Initial revision
57*59d799daSIngo Weinhold  */
58*59d799daSIngo Weinhold 
59*59d799daSIngo Weinhold #include "m_apm_lc.h"
60*59d799daSIngo Weinhold 
61*59d799daSIngo Weinhold static	M_APM   M_last_xx_input;
62*59d799daSIngo Weinhold static	M_APM   M_last_xx_log;
63*59d799daSIngo Weinhold static	int     M_last_log_digits;
64*59d799daSIngo Weinhold static	int     M_size_flag = 0;
65*59d799daSIngo Weinhold 
66*59d799daSIngo Weinhold /****************************************************************************/
M_free_all_pow()67*59d799daSIngo Weinhold void	M_free_all_pow()
68*59d799daSIngo Weinhold {
69*59d799daSIngo Weinhold if (M_size_flag != 0)
70*59d799daSIngo Weinhold   {
71*59d799daSIngo Weinhold    m_apm_free(M_last_xx_input);
72*59d799daSIngo Weinhold    m_apm_free(M_last_xx_log);
73*59d799daSIngo Weinhold    M_size_flag = 0;
74*59d799daSIngo Weinhold   }
75*59d799daSIngo Weinhold }
76*59d799daSIngo Weinhold /****************************************************************************/
77*59d799daSIngo Weinhold /*
78*59d799daSIngo Weinhold 	Calculate the POW function by calling EXP :
79*59d799daSIngo Weinhold 
80*59d799daSIngo Weinhold                   Y      A
81*59d799daSIngo Weinhold                  X   =  e    where A = Y * log(X)
82*59d799daSIngo Weinhold */
m_apm_pow(M_APM rr,int places,M_APM xx,M_APM yy)83*59d799daSIngo Weinhold void	m_apm_pow(M_APM rr, int places, M_APM xx, M_APM yy)
84*59d799daSIngo Weinhold {
85*59d799daSIngo Weinhold int	iflag, pflag;
86*59d799daSIngo Weinhold char    sbuf[64];
87*59d799daSIngo Weinhold M_APM   tmp8, tmp9;
88*59d799daSIngo Weinhold 
89*59d799daSIngo Weinhold /* if yy == 0, return 1 */
90*59d799daSIngo Weinhold 
91*59d799daSIngo Weinhold if (yy->m_apm_sign == 0)
92*59d799daSIngo Weinhold   {
93*59d799daSIngo Weinhold    m_apm_copy(rr, MM_One);
94*59d799daSIngo Weinhold    return;
95*59d799daSIngo Weinhold   }
96*59d799daSIngo Weinhold 
97*59d799daSIngo Weinhold /* if xx == 0, return 0 */
98*59d799daSIngo Weinhold 
99*59d799daSIngo Weinhold if (xx->m_apm_sign == 0)
100*59d799daSIngo Weinhold   {
101*59d799daSIngo Weinhold    M_set_to_zero(rr);
102*59d799daSIngo Weinhold    return;
103*59d799daSIngo Weinhold   }
104*59d799daSIngo Weinhold 
105*59d799daSIngo Weinhold if (M_size_flag == 0)       /* init locals on first call */
106*59d799daSIngo Weinhold   {
107*59d799daSIngo Weinhold    M_size_flag       = M_get_sizeof_int();
108*59d799daSIngo Weinhold    M_last_log_digits = 0;
109*59d799daSIngo Weinhold    M_last_xx_input   = m_apm_init();
110*59d799daSIngo Weinhold    M_last_xx_log     = m_apm_init();
111*59d799daSIngo Weinhold   }
112*59d799daSIngo Weinhold 
113*59d799daSIngo Weinhold /*
114*59d799daSIngo Weinhold  *  if 'yy' is a small enough integer, call the more
115*59d799daSIngo Weinhold  *  efficient _integer_pow function.
116*59d799daSIngo Weinhold  */
117*59d799daSIngo Weinhold 
118*59d799daSIngo Weinhold if (m_apm_is_integer(yy))
119*59d799daSIngo Weinhold   {
120*59d799daSIngo Weinhold    iflag = FALSE;
121*59d799daSIngo Weinhold 
122*59d799daSIngo Weinhold    if (M_size_flag == 2)            /* 16 bit compilers */
123*59d799daSIngo Weinhold      {
124*59d799daSIngo Weinhold       if (yy->m_apm_exponent <= 4)
125*59d799daSIngo Weinhold         iflag = TRUE;
126*59d799daSIngo Weinhold      }
127*59d799daSIngo Weinhold    else                             /* >= 32 bit compilers */
128*59d799daSIngo Weinhold      {
129*59d799daSIngo Weinhold       if (yy->m_apm_exponent <= 7)
130*59d799daSIngo Weinhold         iflag = TRUE;
131*59d799daSIngo Weinhold      }
132*59d799daSIngo Weinhold 
133*59d799daSIngo Weinhold    if (iflag)
134*59d799daSIngo Weinhold      {
135*59d799daSIngo Weinhold       m_apm_to_integer_string(sbuf, yy);
136*59d799daSIngo Weinhold       m_apm_integer_pow(rr, places, xx, atoi(sbuf));
137*59d799daSIngo Weinhold       return;
138*59d799daSIngo Weinhold      }
139*59d799daSIngo Weinhold   }
140*59d799daSIngo Weinhold 
141*59d799daSIngo Weinhold tmp8 = M_get_stack_var();
142*59d799daSIngo Weinhold tmp9 = M_get_stack_var();
143*59d799daSIngo Weinhold 
144*59d799daSIngo Weinhold /*
145*59d799daSIngo Weinhold  *    If parameter 'X' is the same this call as it
146*59d799daSIngo Weinhold  *    was the previous call, re-use the saved log
147*59d799daSIngo Weinhold  *    calculation from last time.
148*59d799daSIngo Weinhold  */
149*59d799daSIngo Weinhold 
150*59d799daSIngo Weinhold pflag = FALSE;
151*59d799daSIngo Weinhold 
152*59d799daSIngo Weinhold if (M_last_log_digits >= places)
153*59d799daSIngo Weinhold   {
154*59d799daSIngo Weinhold    if (m_apm_compare(xx, M_last_xx_input) == 0)
155*59d799daSIngo Weinhold      pflag = TRUE;
156*59d799daSIngo Weinhold   }
157*59d799daSIngo Weinhold 
158*59d799daSIngo Weinhold if (pflag)
159*59d799daSIngo Weinhold   {
160*59d799daSIngo Weinhold    m_apm_round(tmp9, (places + 8), M_last_xx_log);
161*59d799daSIngo Weinhold   }
162*59d799daSIngo Weinhold else
163*59d799daSIngo Weinhold   {
164*59d799daSIngo Weinhold    m_apm_log(tmp9, (places + 8), xx);
165*59d799daSIngo Weinhold 
166*59d799daSIngo Weinhold    M_last_log_digits = places + 2;
167*59d799daSIngo Weinhold 
168*59d799daSIngo Weinhold    /* save the 'X' input value and the log calculation */
169*59d799daSIngo Weinhold 
170*59d799daSIngo Weinhold    m_apm_copy(M_last_xx_input, xx);
171*59d799daSIngo Weinhold    m_apm_copy(M_last_xx_log, tmp9);
172*59d799daSIngo Weinhold   }
173*59d799daSIngo Weinhold 
174*59d799daSIngo Weinhold m_apm_multiply(tmp8, tmp9, yy);
175*59d799daSIngo Weinhold m_apm_exp(rr, places, tmp8);
176*59d799daSIngo Weinhold M_restore_stack(2);                    /* restore the 2 locals we used here */
177*59d799daSIngo Weinhold }
178*59d799daSIngo Weinhold /****************************************************************************/
179