5
* Copyright (C) 2000 - 2007 Michael C. Ring
7
* Permission to use, copy, and distribute this software and its
8
* documentation for any purpose with or without fee is hereby granted,
9
* provided that the above copyright notice appear in all copies and
10
* that both that copyright notice and this permission notice appear
11
* in supporting documentation.
13
* Permission to modify the software is granted. Permission to distribute
14
* the modified code is granted. Modifications are to be distributed by
15
* using the file 'license.txt' as a template to modify the file header.
16
* 'license.txt' is available in the official MAPM distribution.
18
* This software is provided "as is" without express or implied warranty.
23
* This file contains the POW function.
28
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
30
static M_APM M_last_xx_input;
31
static M_APM M_last_xx_log;
32
static int M_last_log_digits;
33
static int M_size_flag = 0;
35
/****************************************************************************/
40
m_apm_free(M_last_xx_input);
41
m_apm_free(M_last_xx_log);
45
/****************************************************************************/
47
Calculate the POW function by calling EXP :
50
X = e where A = Y * log(X)
52
void m_apm_pow(M_APM rr, int places, M_APM xx, M_APM yy)
58
/* if yy == 0, return 1 */
60
if (yy->m_apm_sign == 0)
62
m_apm_copy(rr, MM_One);
66
/* if xx == 0, return 0 */
68
if (xx->m_apm_sign == 0)
74
if (M_size_flag == 0) /* init locals on first call */
76
M_size_flag = M_get_sizeof_int();
77
M_last_log_digits = 0;
78
M_last_xx_input = m_apm_init();
79
M_last_xx_log = m_apm_init();
83
* if 'yy' is a small enough integer, call the more
84
* efficient _integer_pow function.
87
if (m_apm_is_integer(yy))
91
if (M_size_flag == 2) /* 16 bit compilers */
93
if (yy->m_apm_exponent <= 4)
96
else /* >= 32 bit compilers */
98
if (yy->m_apm_exponent <= 7)
104
m_apm_to_integer_string(sbuf, yy);
105
m_apm_integer_pow(rr, places, xx, atoi(sbuf));
110
tmp8 = M_get_stack_var();
111
tmp9 = M_get_stack_var();
114
* If parameter 'X' is the same this call as it
115
* was the previous call, re-use the saved log
116
* calculation from last time.
121
if (M_last_log_digits >= places)
123
if (m_apm_compare(xx, M_last_xx_input) == 0)
129
m_apm_round(tmp9, (places + 8), M_last_xx_log);
133
m_apm_log(tmp9, (places + 8), xx);
135
M_last_log_digits = places + 2;
137
/* save the 'X' input value and the log calculation */
139
m_apm_copy(M_last_xx_input, xx);
140
m_apm_copy(M_last_xx_log, tmp9);
143
m_apm_multiply(tmp8, tmp9, yy);
144
m_apm_exp(rr, places, tmp8);
145
M_restore_stack(2); /* restore the 2 locals we used here */
147
/****************************************************************************/