1 /*-------------------------------------------------------------------------
2 logf.c - Computes the natural log of a 32 bit float as outlined in [1].
4 Copyright (C) 2001, 2002, Jesus Calvino-Fraga, jesusc@ieee.org
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; see the file COPYING. If not, write to the
18 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
21 As a special exception, if you link this library with other files,
22 some of which are compiled with SDCC, to produce an executable,
23 this library does not by itself cause the resulting executable to
24 be covered by the GNU General Public License. This exception does
25 not however invalidate any other reasons why the executable file
26 might be covered by the GNU General Public License.
27 -------------------------------------------------------------------------*/
29 /* [1] William James Cody and W. M. Waite. _Software manual for the
30 elementary functions_, Englewood Cliffs, N.J.:Prentice-Hall, 1980. */
32 /* Version 1.0 - Initial release */
34 #define __SDCC_MATH_LIB
41 #define __SDCC_FLOAT_LIB
44 // TODO: share with other temps
45 static __data
unsigned char logf_tmp
[4];
52 // extract the two input, placing it into:
53 // sign exponent mantiassa
54 // ---- -------- ---------
55 // x: sign_a exp_a r4/r3/r2
59 jnb sign_a
, logf_zero_check
60 // TODO: set errno to EDOM (negative numbers not allowed)
66 // TODO: set errno to ERANGE (zero not allowed)
78 mov (_logf_tmp
+ 0), a
// y = 0
79 mov (_logf_tmp
+ 1), a
80 mov (_logf_tmp
+ 2), a
81 mov (_logf_tmp
+ 3), a
82 mov dptr
, #__fs_natural_log_table
85 mov ar7
, r4
// r7/r6/r5 = x >> i
90 lcall __fs_cordic_rshift_r765_unsigned
91 mov a
, r1
// check if x + (x >> i) > 1.0
101 mov a
, r1
// x = x + (x >> i)
113 clr a
// y = y + log_table[i]
115 add a
, (_logf_tmp
+ 0)
116 mov (_logf_tmp
+ 0), a
119 addc a
, (_logf_tmp
+ 1)
120 mov (_logf_tmp
+ 1), a
123 addc a
, (_logf_tmp
+ 2)
124 mov (_logf_tmp
+ 2), a
127 addc a
, (_logf_tmp
+ 3)
128 mov (_logf_tmp
+ 3), a
135 cjne r0
, #30, logf_cordic_loop
136 // at this point, _logf_tmp has the natural log of the positive
137 // normalized fractional part (0.5 to 1.0 -> 0.693 to 0.0)
138 mov r4
, (_logf_tmp
+ 3)
139 mov r3
, (_logf_tmp
+ 2)
140 mov r2
, (_logf_tmp
+ 1)
141 mov r1
, (_logf_tmp
+ 0)
146 cjne a
, #126, logf_exponent
147 // if the input exponent was 126, then we don't need to add
148 // anything and we can just return the with we have already
150 // TODO: which of these gives best accuracy???
151 lcall fs_zerocheck_return
152 //lcall fs_round_and_return
156 // the input exponent was greater than 126
162 // the input exponent was less than 126
167 // r0 has abs(exp - 126)
169 // put the log of faction into b, so we can use a to compute
170 // the offset to be added to it or subtracted from it
172 // multiply r0 by log(2), or r0 * 0xB17218
194 // turn r0 * log(2) into a proper float
197 // now just add log(fractional) +/- log(2) * abs(exp - 126)
198 lcall fsadd_direct_entry
201 #pragma less_pedantic
204 #else // not MATH_ASM_MCS51
206 /*Constants for 24 bits or less (8 decimal digits)*/
207 #define A0 -0.5527074855E+0
208 #define B0 -0.6632718214E+1
212 #define C0 0.70710678118654752440
213 #define C1 0.693359375 /*355.0/512.0*/
214 #define C2 -2.121944400546905827679E-4
216 float logf(float x
) _FLOAT_FUNC_REENTRANT
218 #if defined(__SDCC_mcs51) && defined(__SDCC_MODEL_SMALL) \
219 && !defined(__SDCC_NOOVERLAY)
223 float f
, z
, w
, znum
, zden
, xn
;
246 Rz
=z
+z
*(w
*A(w
)/B(w
));
248 return ((xn
*C2
+Rz
)+xn
*C1
);